Line data Source code
1 : /* Expansion pass for OMP directives. Outlines regions of certain OMP
2 : directives to separate functions, converts others into explicit calls to the
3 : runtime library (libgomp) and so forth
4 :
5 : Copyright (C) 2005-2026 Free Software Foundation, Inc.
6 :
7 : This file is part of GCC.
8 :
9 : GCC is free software; you can redistribute it and/or modify it under
10 : the terms of the GNU General Public License as published by the Free
11 : Software Foundation; either version 3, or (at your option) any later
12 : version.
13 :
14 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 : for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with GCC; see the file COPYING3. If not see
21 : <http://www.gnu.org/licenses/>. */
22 :
23 : #include "config.h"
24 : #include "system.h"
25 : #include "coretypes.h"
26 : #include "memmodel.h"
27 : #include "backend.h"
28 : #include "target.h"
29 : #include "rtl.h"
30 : #include "tree.h"
31 : #include "gimple.h"
32 : #include "cfghooks.h"
33 : #include "tree-pass.h"
34 : #include "ssa.h"
35 : #include "optabs.h"
36 : #include "cgraph.h"
37 : #include "pretty-print.h"
38 : #include "diagnostic-core.h"
39 : #include "fold-const.h"
40 : #include "stor-layout.h"
41 : #include "cfganal.h"
42 : #include "internal-fn.h"
43 : #include "gimplify.h"
44 : #include "gimple-iterator.h"
45 : #include "gimplify-me.h"
46 : #include "gimple-walk.h"
47 : #include "tree-cfg.h"
48 : #include "tree-into-ssa.h"
49 : #include "tree-ssa.h"
50 : #include "splay-tree.h"
51 : #include "cfgloop.h"
52 : #include "omp-general.h"
53 : #include "omp-offload.h"
54 : #include "tree-cfgcleanup.h"
55 : #include "alloc-pool.h"
56 : #include "symbol-summary.h"
57 : #include "gomp-constants.h"
58 : #include "gimple-pretty-print.h"
59 : #include "stringpool.h"
60 : #include "attribs.h"
61 : #include "tree-eh.h"
62 : #include "opts.h"
63 :
64 : /* OMP region information. Every parallel and workshare
65 : directive is enclosed between two markers, the OMP_* directive
66 : and a corresponding GIMPLE_OMP_RETURN statement. */
67 :
68 : struct omp_region
69 : {
70 : /* The enclosing region. */
71 : struct omp_region *outer;
72 :
73 : /* First child region. */
74 : struct omp_region *inner;
75 :
76 : /* Next peer region. */
77 : struct omp_region *next;
78 :
79 : /* Block containing the omp directive as its last stmt. */
80 : basic_block entry;
81 :
82 : /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
83 : basic_block exit;
84 :
85 : /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
86 : basic_block cont;
87 :
88 : /* If this is a combined parallel+workshare region, this is a list
89 : of additional arguments needed by the combined parallel+workshare
90 : library call. */
91 : vec<tree, va_gc> *ws_args;
92 :
93 : /* The code for the omp directive of this region. */
94 : enum gimple_code type;
95 :
96 : /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
97 : enum omp_clause_schedule_kind sched_kind;
98 :
99 : /* Schedule modifiers. */
100 : unsigned char sched_modifiers;
101 :
102 : /* True if this is a combined parallel+workshare region. */
103 : bool is_combined_parallel;
104 :
105 : /* Copy of fd.lastprivate_conditional != 0. */
106 : bool has_lastprivate_conditional;
107 :
108 : /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
109 : a depend clause. */
110 : gomp_ordered *ord_stmt;
111 : };
112 :
113 : static struct omp_region *root_omp_region;
114 : static bool omp_any_child_fn_dumped;
115 :
116 : static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
117 : bool = false);
118 : static gphi *find_phi_with_arg_on_edge (tree, edge);
119 : static void expand_omp (struct omp_region *region);
120 :
121 : /* Return true if REGION is a combined parallel+workshare region. */
122 :
123 : static inline bool
124 43626 : is_combined_parallel (struct omp_region *region)
125 : {
126 43626 : return region->is_combined_parallel;
127 : }
128 :
129 : /* Return true is REGION is or is contained within an offload region. */
130 :
131 : static bool
132 11189 : is_in_offload_region (struct omp_region *region)
133 : {
134 30060 : gimple *entry_stmt = last_nondebug_stmt (region->entry);
135 30060 : if (is_gimple_omp (entry_stmt)
136 29104 : && is_gimple_omp_offloaded (entry_stmt))
137 : return true;
138 25750 : else if (region->outer)
139 : return is_in_offload_region (region->outer);
140 : else
141 6879 : return (lookup_attribute ("omp declare target",
142 6879 : DECL_ATTRIBUTES (current_function_decl))
143 6879 : != NULL);
144 : }
145 :
146 : /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
147 : is the immediate dominator of PAR_ENTRY_BB, return true if there
148 : are no data dependencies that would prevent expanding the parallel
149 : directive at PAR_ENTRY_BB as a combined parallel+workshare region.
150 :
151 : When expanding a combined parallel+workshare region, the call to
152 : the child function may need additional arguments in the case of
153 : GIMPLE_OMP_FOR regions. In some cases, these arguments are
154 : computed out of variables passed in from the parent to the child
155 : via 'struct .omp_data_s'. For instance:
156 :
157 : #pragma omp parallel for schedule (guided, i * 4)
158 : for (j ...)
159 :
160 : Is lowered into:
161 :
162 : # BLOCK 2 (PAR_ENTRY_BB)
163 : .omp_data_o.i = i;
164 : #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
165 :
166 : # BLOCK 3 (WS_ENTRY_BB)
167 : .omp_data_i = &.omp_data_o;
168 : D.1667 = .omp_data_i->i;
169 : D.1598 = D.1667 * 4;
170 : #pragma omp for schedule (guided, D.1598)
171 :
172 : When we outline the parallel region, the call to the child function
173 : 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
174 : that value is computed *after* the call site. So, in principle we
175 : cannot do the transformation.
176 :
177 : To see whether the code in WS_ENTRY_BB blocks the combined
178 : parallel+workshare call, we collect all the variables used in the
179 : GIMPLE_OMP_FOR header check whether they appear on the LHS of any
180 : statement in WS_ENTRY_BB. If so, then we cannot emit the combined
181 : call.
182 :
183 : FIXME. If we had the SSA form built at this point, we could merely
184 : hoist the code in block 3 into block 2 and be done with it. But at
185 : this point we don't have dataflow information and though we could
186 : hack something up here, it is really not worth the aggravation. */
187 :
188 : static bool
189 9110 : workshare_safe_to_combine_p (basic_block ws_entry_bb)
190 : {
191 9110 : struct omp_for_data fd;
192 9110 : gimple *ws_stmt = last_nondebug_stmt (ws_entry_bb);
193 :
194 9110 : if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
195 : return true;
196 :
197 8987 : gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
198 8987 : if (gimple_omp_for_kind (ws_stmt) != GF_OMP_FOR_KIND_FOR)
199 : return false;
200 :
201 8970 : omp_extract_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
202 :
203 8970 : if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
204 : return false;
205 7191 : if (fd.iter_type != long_integer_type_node)
206 : return false;
207 :
208 : /* FIXME. We give up too easily here. If any of these arguments
209 : are not constants, they will likely involve variables that have
210 : been mapped into fields of .omp_data_s for sharing with the child
211 : function. With appropriate data flow, it would be possible to
212 : see through this. */
213 1508 : if (!is_gimple_min_invariant (fd.loop.n1)
214 1278 : || !is_gimple_min_invariant (fd.loop.n2)
215 1149 : || !is_gimple_min_invariant (fd.loop.step)
216 2642 : || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
217 376 : return false;
218 :
219 : return true;
220 : }
221 :
222 : /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
223 : presence (SIMD_SCHEDULE). */
224 :
225 : static tree
226 8362 : omp_adjust_chunk_size (tree chunk_size, bool simd_schedule, bool offload)
227 : {
228 8362 : if (!simd_schedule || integer_zerop (chunk_size))
229 : return chunk_size;
230 :
231 34 : tree vf;
232 34 : tree type = TREE_TYPE (chunk_size);
233 :
234 34 : if (offload)
235 : {
236 2 : cfun->curr_properties &= ~PROP_gimple_lomp_dev;
237 2 : vf = build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_GOMP_MAX_VF,
238 : unsigned_type_node, 0);
239 2 : vf = fold_convert (type, vf);
240 : }
241 : else
242 : {
243 32 : poly_uint64 vf_num = omp_max_vf (false);
244 32 : if (known_eq (vf_num, 1U))
245 8362 : return chunk_size;
246 31 : vf = build_int_cst (type, vf_num);
247 : }
248 :
249 33 : tree vf_minus_one = fold_build2 (MINUS_EXPR, type, vf,
250 : build_int_cst (type, 1));
251 33 : tree negative_vf = fold_build1 (NEGATE_EXPR, type, vf);
252 33 : chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size, vf_minus_one);
253 33 : return fold_build2 (BIT_AND_EXPR, type, chunk_size, negative_vf);
254 : }
255 :
256 : /* Collect additional arguments needed to emit a combined
257 : parallel+workshare call. WS_STMT is the workshare directive being
258 : expanded. */
259 :
260 : static vec<tree, va_gc> *
261 1200 : get_ws_args_for (gimple *par_stmt, gimple *ws_stmt, bool offload)
262 : {
263 1200 : tree t;
264 1200 : location_t loc = gimple_location (ws_stmt);
265 1200 : vec<tree, va_gc> *ws_args;
266 :
267 1200 : if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
268 : {
269 1084 : struct omp_for_data fd;
270 1084 : tree n1, n2;
271 :
272 1084 : omp_extract_for_data (for_stmt, &fd, NULL);
273 1084 : n1 = fd.loop.n1;
274 1084 : n2 = fd.loop.n2;
275 :
276 1084 : if (gimple_omp_for_combined_into_p (for_stmt))
277 : {
278 769 : tree innerc
279 769 : = omp_find_clause (gimple_omp_parallel_clauses (par_stmt),
280 : OMP_CLAUSE__LOOPTEMP_);
281 769 : gcc_assert (innerc);
282 769 : n1 = OMP_CLAUSE_DECL (innerc);
283 769 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
284 : OMP_CLAUSE__LOOPTEMP_);
285 769 : gcc_assert (innerc);
286 769 : n2 = OMP_CLAUSE_DECL (innerc);
287 : }
288 :
289 1084 : vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
290 :
291 1084 : t = fold_convert_loc (loc, long_integer_type_node, n1);
292 1084 : ws_args->quick_push (t);
293 :
294 1084 : t = fold_convert_loc (loc, long_integer_type_node, n2);
295 1084 : ws_args->quick_push (t);
296 :
297 1084 : t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
298 1084 : ws_args->quick_push (t);
299 :
300 1084 : if (fd.chunk_size)
301 : {
302 538 : t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
303 538 : t = omp_adjust_chunk_size (t, fd.simd_schedule, offload);
304 538 : ws_args->quick_push (t);
305 : }
306 :
307 1084 : return ws_args;
308 : }
309 116 : else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
310 : {
311 : /* Number of sections is equal to the number of edges from the
312 : GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
313 : the exit of the sections region. */
314 116 : basic_block bb = single_succ (gimple_bb (ws_stmt));
315 232 : t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
316 116 : vec_alloc (ws_args, 1);
317 116 : ws_args->quick_push (t);
318 116 : return ws_args;
319 : }
320 :
321 0 : gcc_unreachable ();
322 : }
323 :
324 : /* Discover whether REGION is a combined parallel+workshare region. */
325 :
326 : static void
327 16400 : determine_parallel_type (struct omp_region *region)
328 : {
329 16400 : basic_block par_entry_bb, par_exit_bb;
330 16400 : basic_block ws_entry_bb, ws_exit_bb;
331 :
332 16400 : if (region == NULL || region->inner == NULL
333 14872 : || region->exit == NULL || region->inner->exit == NULL
334 14861 : || region->inner->cont == NULL)
335 : return;
336 :
337 : /* We only support parallel+for and parallel+sections. */
338 10387 : if (region->type != GIMPLE_OMP_PARALLEL
339 10387 : || (region->inner->type != GIMPLE_OMP_FOR
340 297 : && region->inner->type != GIMPLE_OMP_SECTIONS))
341 : return;
342 :
343 : /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
344 : WS_EXIT_BB -> PAR_EXIT_BB. */
345 10267 : par_entry_bb = region->entry;
346 10267 : par_exit_bb = region->exit;
347 10267 : ws_entry_bb = region->inner->entry;
348 10267 : ws_exit_bb = region->inner->exit;
349 :
350 : /* Give up for task reductions on the parallel, while it is implementable,
351 : adding another big set of APIs or slowing down the normal paths is
352 : not acceptable. */
353 10267 : tree pclauses
354 10267 : = gimple_omp_parallel_clauses (last_nondebug_stmt (par_entry_bb));
355 10267 : if (omp_find_clause (pclauses, OMP_CLAUSE__REDUCTEMP_))
356 : return;
357 :
358 10244 : if (single_succ (par_entry_bb) == ws_entry_bb
359 9147 : && single_succ (ws_exit_bb) == par_exit_bb
360 9110 : && workshare_safe_to_combine_p (ws_entry_bb)
361 11499 : && (gimple_omp_parallel_combined_p (last_nondebug_stmt (par_entry_bb))
362 7 : || (last_and_only_stmt (ws_entry_bb)
363 2 : && last_and_only_stmt (par_exit_bb))))
364 : {
365 1248 : gimple *par_stmt = last_nondebug_stmt (par_entry_bb);
366 1248 : gimple *ws_stmt = last_nondebug_stmt (ws_entry_bb);
367 :
368 1248 : if (region->inner->type == GIMPLE_OMP_FOR)
369 : {
370 : /* If this is a combined parallel loop, we need to determine
371 : whether or not to use the combined library calls. There
372 : are two cases where we do not apply the transformation:
373 : static loops and any kind of ordered loop. In the first
374 : case, we already open code the loop so there is no need
375 : to do anything else. In the latter case, the combined
376 : parallel loop call would still need extra synchronization
377 : to implement ordered semantics, so there would not be any
378 : gain in using the combined call. */
379 1128 : tree clauses = gimple_omp_for_clauses (ws_stmt);
380 1128 : tree c = omp_find_clause (clauses, OMP_CLAUSE_SCHEDULE);
381 1128 : if (c == NULL
382 1110 : || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
383 : == OMP_CLAUSE_SCHEDULE_STATIC)
384 1096 : || omp_find_clause (clauses, OMP_CLAUSE_ORDERED)
385 1084 : || omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_)
386 2212 : || ((c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_))
387 14 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
388 : return;
389 : }
390 120 : else if (region->inner->type == GIMPLE_OMP_SECTIONS
391 240 : && (omp_find_clause (gimple_omp_sections_clauses (ws_stmt),
392 : OMP_CLAUSE__REDUCTEMP_)
393 120 : || omp_find_clause (gimple_omp_sections_clauses (ws_stmt),
394 : OMP_CLAUSE__CONDTEMP_)))
395 : return;
396 :
397 1200 : region->is_combined_parallel = true;
398 1200 : region->inner->is_combined_parallel = true;
399 1200 : region->ws_args = get_ws_args_for (par_stmt, ws_stmt,
400 : is_in_offload_region (region));
401 : }
402 : }
403 :
404 : /* Debugging dumps for parallel regions. */
405 : void dump_omp_region (FILE *, struct omp_region *, int);
406 : void debug_omp_region (struct omp_region *);
407 : void debug_all_omp_regions (void);
408 :
409 : /* Dump the parallel region tree rooted at REGION. */
410 :
411 : void
412 402 : dump_omp_region (FILE *file, struct omp_region *region, int indent)
413 : {
414 473 : fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
415 473 : gimple_code_name[region->type]);
416 :
417 473 : if (region->inner)
418 118 : dump_omp_region (file, region->inner, indent + 4);
419 :
420 473 : if (region->cont)
421 : {
422 223 : fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
423 : region->cont->index);
424 : }
425 :
426 473 : if (region->exit)
427 450 : fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
428 : region->exit->index);
429 : else
430 23 : fprintf (file, "%*s[no exit marker]\n", indent, "");
431 :
432 473 : if (region->next)
433 : dump_omp_region (file, region->next, indent);
434 402 : }
435 :
436 : DEBUG_FUNCTION void
437 0 : debug_omp_region (struct omp_region *region)
438 : {
439 0 : dump_omp_region (stderr, region, 0);
440 0 : }
441 :
442 : DEBUG_FUNCTION void
443 0 : debug_all_omp_regions (void)
444 : {
445 0 : dump_omp_region (stderr, root_omp_region, 0);
446 0 : }
447 :
448 : /* Create a new parallel region starting at STMT inside region PARENT. */
449 :
450 : static struct omp_region *
451 247721 : new_omp_region (basic_block bb, enum gimple_code type,
452 : struct omp_region *parent)
453 : {
454 247721 : struct omp_region *region = XCNEW (struct omp_region);
455 :
456 247721 : region->outer = parent;
457 247721 : region->entry = bb;
458 247721 : region->type = type;
459 :
460 247721 : if (parent)
461 : {
462 : /* This is a nested region. Add it to the list of inner
463 : regions in PARENT. */
464 127890 : region->next = parent->inner;
465 127890 : parent->inner = region;
466 : }
467 : else
468 : {
469 : /* This is a toplevel region. Add it to the list of toplevel
470 : regions in ROOT_OMP_REGION. */
471 119831 : region->next = root_omp_region;
472 119831 : root_omp_region = region;
473 : }
474 :
475 247721 : return region;
476 : }
477 :
478 : /* Release the memory associated with the region tree rooted at REGION. */
479 :
480 : static void
481 247721 : free_omp_region_1 (struct omp_region *region)
482 : {
483 247721 : struct omp_region *i, *n;
484 :
485 375611 : for (i = region->inner; i ; i = n)
486 : {
487 127890 : n = i->next;
488 127890 : free_omp_region_1 (i);
489 : }
490 :
491 247721 : free (region);
492 247721 : }
493 :
494 : /* Release the memory for the entire omp region tree. */
495 :
496 : void
497 3051790 : omp_free_regions (void)
498 : {
499 3051790 : struct omp_region *r, *n;
500 3171621 : for (r = root_omp_region; r ; r = n)
501 : {
502 119831 : n = r->next;
503 119831 : free_omp_region_1 (r);
504 : }
505 3051790 : root_omp_region = NULL;
506 3051790 : }
507 :
508 : /* A convenience function to build an empty GIMPLE_COND with just the
509 : condition. */
510 :
511 : static gcond *
512 113167 : gimple_build_cond_empty (tree cond)
513 : {
514 113167 : enum tree_code pred_code;
515 113167 : tree lhs, rhs;
516 :
517 113167 : gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
518 113167 : return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
519 : }
520 :
521 : /* Change DECL_CONTEXT of CHILD_FNDECL to that of the parent function.
522 : Add CHILD_FNDECL to decl chain of the supercontext of the block
523 : ENTRY_BLOCK - this is the block which originally contained the
524 : code from which CHILD_FNDECL was created.
525 :
526 : Together, these actions ensure that the debug info for the outlined
527 : function will be emitted with the correct lexical scope. */
528 :
529 : static void
530 43969 : adjust_context_and_scope (struct omp_region *region, tree entry_block,
531 : tree child_fndecl)
532 : {
533 43969 : tree parent_fndecl = NULL_TREE;
534 43969 : gimple *entry_stmt;
535 : /* OMP expansion expands inner regions before outer ones, so if
536 : we e.g. have explicit task region nested in parallel region, when
537 : expanding the task region current_function_decl will be the original
538 : source function, but we actually want to use as context the child
539 : function of the parallel. */
540 43969 : for (region = region->outer;
541 65143 : region && parent_fndecl == NULL_TREE; region = region->outer)
542 21174 : switch (region->type)
543 : {
544 6870 : case GIMPLE_OMP_PARALLEL:
545 6870 : case GIMPLE_OMP_TASK:
546 6870 : case GIMPLE_OMP_TEAMS:
547 6870 : entry_stmt = last_nondebug_stmt (region->entry);
548 6870 : parent_fndecl = gimple_omp_taskreg_child_fn (entry_stmt);
549 6870 : break;
550 4559 : case GIMPLE_OMP_TARGET:
551 4559 : entry_stmt = last_nondebug_stmt (region->entry);
552 4559 : parent_fndecl
553 4559 : = gimple_omp_target_child_fn (as_a <gomp_target *> (entry_stmt));
554 4559 : break;
555 : default:
556 : break;
557 : }
558 :
559 43969 : if (parent_fndecl == NULL_TREE)
560 35651 : parent_fndecl = current_function_decl;
561 43969 : DECL_CONTEXT (child_fndecl) = parent_fndecl;
562 :
563 43969 : if (entry_block != NULL_TREE && TREE_CODE (entry_block) == BLOCK)
564 : {
565 43935 : tree b = BLOCK_SUPERCONTEXT (entry_block);
566 43935 : if (TREE_CODE (b) == BLOCK)
567 : {
568 43801 : DECL_CHAIN (child_fndecl) = BLOCK_VARS (b);
569 43801 : BLOCK_VARS (b) = child_fndecl;
570 : }
571 : }
572 43969 : }
573 :
574 : /* Build the function calls to GOMP_parallel etc to actually
575 : generate the parallel operation. REGION is the parallel region
576 : being expanded. BB is the block where to insert the code. WS_ARGS
577 : will be set if this is a call to a combined parallel+workshare
578 : construct, it contains the list of additional arguments needed by
579 : the workshare construct. */
580 :
581 : static void
582 16400 : expand_parallel_call (struct omp_region *region, basic_block bb,
583 : gomp_parallel *entry_stmt,
584 : vec<tree, va_gc> *ws_args)
585 : {
586 16400 : tree t, t1, t2, val, cond, c, clauses, flags;
587 16400 : gimple_stmt_iterator gsi;
588 16400 : gimple *stmt;
589 16400 : enum built_in_function start_ix;
590 16400 : int start_ix2;
591 16400 : location_t clause_loc;
592 16400 : vec<tree, va_gc> *args;
593 :
594 16400 : clauses = gimple_omp_parallel_clauses (entry_stmt);
595 :
596 : /* Determine what flavor of GOMP_parallel we will be
597 : emitting. */
598 16400 : start_ix = BUILT_IN_GOMP_PARALLEL;
599 16400 : tree rtmp = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
600 16400 : if (rtmp)
601 : start_ix = BUILT_IN_GOMP_PARALLEL_REDUCTIONS;
602 16340 : else if (is_combined_parallel (region))
603 : {
604 1200 : switch (region->inner->type)
605 : {
606 1084 : case GIMPLE_OMP_FOR:
607 1084 : gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
608 1084 : switch (region->inner->sched_kind)
609 : {
610 546 : case OMP_CLAUSE_SCHEDULE_RUNTIME:
611 : /* For lastprivate(conditional:), our implementation
612 : requires monotonic behavior. */
613 546 : if (region->inner->has_lastprivate_conditional != 0)
614 : start_ix2 = 3;
615 544 : else if ((region->inner->sched_modifiers
616 : & OMP_CLAUSE_SCHEDULE_NONMONOTONIC) != 0)
617 : start_ix2 = 6;
618 530 : else if ((region->inner->sched_modifiers
619 : & OMP_CLAUSE_SCHEDULE_MONOTONIC) == 0)
620 : start_ix2 = 7;
621 : else
622 16 : start_ix2 = 3;
623 : break;
624 538 : case OMP_CLAUSE_SCHEDULE_DYNAMIC:
625 538 : case OMP_CLAUSE_SCHEDULE_GUIDED:
626 538 : if ((region->inner->sched_modifiers
627 : & OMP_CLAUSE_SCHEDULE_MONOTONIC) == 0
628 534 : && !region->inner->has_lastprivate_conditional)
629 : {
630 522 : start_ix2 = 3 + region->inner->sched_kind;
631 522 : break;
632 : }
633 : /* FALLTHRU */
634 16 : default:
635 16 : start_ix2 = region->inner->sched_kind;
636 16 : break;
637 : }
638 1084 : start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
639 1084 : start_ix = (enum built_in_function) start_ix2;
640 1084 : break;
641 : case GIMPLE_OMP_SECTIONS:
642 : start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
643 : break;
644 0 : default:
645 0 : gcc_unreachable ();
646 : }
647 : }
648 :
649 : /* By default, the value of NUM_THREADS is zero (selected at run time)
650 : and there is no conditional. */
651 16400 : cond = NULL_TREE;
652 16400 : val = build_int_cst (unsigned_type_node, 0);
653 16400 : flags = build_int_cst (unsigned_type_node, 0);
654 :
655 16400 : c = omp_find_clause (clauses, OMP_CLAUSE_IF);
656 16400 : if (c)
657 963 : cond = OMP_CLAUSE_IF_EXPR (c);
658 :
659 16400 : c = omp_find_clause (clauses, OMP_CLAUSE_NUM_THREADS);
660 16400 : if (c)
661 : {
662 2289 : val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
663 2289 : clause_loc = OMP_CLAUSE_LOCATION (c);
664 2289 : if (TREE_CODE (val) == TREE_LIST)
665 : {
666 957 : if (OMP_CLAUSE_NUM_THREADS_DIMS (c)
667 957 : && (TREE_CHAIN (val) || OMP_CLAUSE_NUM_THREADS_STRICT (c)))
668 : /* Accept 'dim(1),relaxed'. */
669 1 : sorry_at (clause_loc,
670 : "%<num_threads%> clause with %<dims%> modifier");
671 956 : else if (TREE_CHAIN (val))
672 1 : sorry_at (clause_loc,
673 : "%<num_threads%> clause with more than one argument");
674 955 : else if (OMP_CLAUSE_NUM_THREADS_STRICT (c))
675 0 : sorry_at (clause_loc,
676 : "%<num_threads%> clause with %<strict%> modifier");
677 957 : val = TREE_VALUE (val);
678 : }
679 1332 : else if (OMP_CLAUSE_NUM_THREADS_STRICT (c))
680 0 : sorry_at (clause_loc,
681 : "%<num_threads%> clause with %<strict%> modifier");
682 : /* FIXME: Handle OMP_CLAUSE_MESSAGE (only relevant with 'strict'). */
683 : }
684 : else
685 14111 : clause_loc = gimple_location (entry_stmt);
686 :
687 16400 : c = omp_find_clause (clauses, OMP_CLAUSE_PROC_BIND);
688 16400 : if (c)
689 771 : flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
690 :
691 : /* Ensure 'val' is of the correct type. */
692 16400 : val = fold_convert_loc (clause_loc, unsigned_type_node, val);
693 :
694 : /* If we found the clause 'if (cond)', build either
695 : (cond != 0) or (cond ? val : 1u). */
696 16400 : if (cond)
697 : {
698 963 : cond = gimple_boolify (cond);
699 :
700 963 : if (integer_zerop (val))
701 176 : val = fold_build2_loc (clause_loc,
702 : EQ_EXPR, unsigned_type_node, cond,
703 176 : build_int_cst (TREE_TYPE (cond), 0));
704 : else
705 : {
706 787 : basic_block cond_bb, then_bb, else_bb;
707 787 : edge e, e_then, e_else;
708 787 : tree tmp_then, tmp_else, tmp_join, tmp_var;
709 :
710 787 : tmp_var = create_tmp_var (TREE_TYPE (val));
711 787 : if (gimple_in_ssa_p (cfun))
712 : {
713 0 : tmp_then = make_ssa_name (tmp_var);
714 0 : tmp_else = make_ssa_name (tmp_var);
715 0 : tmp_join = make_ssa_name (tmp_var);
716 : }
717 : else
718 : {
719 : tmp_then = tmp_var;
720 : tmp_else = tmp_var;
721 : tmp_join = tmp_var;
722 : }
723 :
724 787 : e = split_block_after_labels (bb);
725 787 : cond_bb = e->src;
726 787 : bb = e->dest;
727 787 : remove_edge (e);
728 :
729 787 : then_bb = create_empty_bb (cond_bb);
730 787 : else_bb = create_empty_bb (then_bb);
731 787 : set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
732 787 : set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
733 :
734 787 : stmt = gimple_build_cond_empty (cond);
735 787 : gsi = gsi_start_bb (cond_bb);
736 787 : gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
737 :
738 787 : gsi = gsi_start_bb (then_bb);
739 787 : expand_omp_build_assign (&gsi, tmp_then, val, true);
740 :
741 787 : gsi = gsi_start_bb (else_bb);
742 787 : expand_omp_build_assign (&gsi, tmp_else,
743 : build_int_cst (unsigned_type_node, 1),
744 : true);
745 :
746 787 : make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
747 787 : make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
748 787 : add_bb_to_loop (then_bb, cond_bb->loop_father);
749 787 : add_bb_to_loop (else_bb, cond_bb->loop_father);
750 787 : e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
751 787 : e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
752 :
753 787 : if (gimple_in_ssa_p (cfun))
754 : {
755 0 : gphi *phi = create_phi_node (tmp_join, bb);
756 0 : add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
757 0 : add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
758 : }
759 :
760 787 : val = tmp_join;
761 : }
762 :
763 963 : gsi = gsi_start_bb (bb);
764 963 : val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
765 : false, GSI_CONTINUE_LINKING);
766 : }
767 :
768 16400 : gsi = gsi_last_nondebug_bb (bb);
769 16400 : t = gimple_omp_parallel_data_arg (entry_stmt);
770 16400 : if (t == NULL)
771 2413 : t1 = null_pointer_node;
772 : else
773 13987 : t1 = build_fold_addr_expr (t);
774 16400 : tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
775 16400 : t2 = build_fold_addr_expr (child_fndecl);
776 :
777 17600 : vec_alloc (args, 4 + vec_safe_length (ws_args));
778 16400 : args->quick_push (t2);
779 16400 : args->quick_push (t1);
780 16400 : args->quick_push (val);
781 16400 : if (ws_args)
782 1200 : args->splice (*ws_args);
783 16400 : args->quick_push (flags);
784 :
785 16400 : t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
786 : builtin_decl_explicit (start_ix), args);
787 :
788 16400 : if (rtmp)
789 : {
790 60 : tree type = TREE_TYPE (OMP_CLAUSE_DECL (rtmp));
791 60 : t = build2 (MODIFY_EXPR, type, OMP_CLAUSE_DECL (rtmp),
792 : fold_convert (type,
793 : fold_convert (pointer_sized_int_node, t)));
794 : }
795 16400 : force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
796 : false, GSI_CONTINUE_LINKING);
797 16400 : }
798 :
799 : /* Build the function call to GOMP_task to actually
800 : generate the task operation. BB is the block where to insert the code. */
801 :
802 : static void
803 3812 : expand_task_call (struct omp_region *region, basic_block bb,
804 : gomp_task *entry_stmt)
805 : {
806 3812 : tree t1, t2, t3;
807 3812 : gimple_stmt_iterator gsi;
808 3812 : location_t loc = gimple_location (entry_stmt);
809 :
810 3812 : tree clauses = gimple_omp_task_clauses (entry_stmt);
811 :
812 3812 : tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF);
813 3812 : tree untied = omp_find_clause (clauses, OMP_CLAUSE_UNTIED);
814 3812 : tree mergeable = omp_find_clause (clauses, OMP_CLAUSE_MERGEABLE);
815 3812 : tree depend = omp_find_clause (clauses, OMP_CLAUSE_DEPEND);
816 3812 : tree finalc = omp_find_clause (clauses, OMP_CLAUSE_FINAL);
817 3812 : tree priority = omp_find_clause (clauses, OMP_CLAUSE_PRIORITY);
818 3812 : tree detach = omp_find_clause (clauses, OMP_CLAUSE_DETACH);
819 :
820 7624 : unsigned int iflags
821 3812 : = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
822 3812 : | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
823 3812 : | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
824 :
825 3812 : bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
826 3812 : tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
827 3812 : tree num_tasks = NULL_TREE;
828 3812 : bool ull = false;
829 3812 : if (taskloop_p)
830 : {
831 1330 : gimple *g = last_nondebug_stmt (region->outer->entry);
832 1330 : gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
833 : && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
834 1330 : struct omp_for_data fd;
835 1330 : omp_extract_for_data (as_a <gomp_for *> (g), &fd, NULL);
836 1330 : startvar = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
837 1330 : endvar = omp_find_clause (OMP_CLAUSE_CHAIN (startvar),
838 : OMP_CLAUSE__LOOPTEMP_);
839 1330 : startvar = OMP_CLAUSE_DECL (startvar);
840 1330 : endvar = OMP_CLAUSE_DECL (endvar);
841 1330 : step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
842 1330 : if (fd.loop.cond_code == LT_EXPR)
843 1278 : iflags |= GOMP_TASK_FLAG_UP;
844 1330 : tree tclauses = gimple_omp_for_clauses (g);
845 1330 : num_tasks = omp_find_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
846 1330 : if (num_tasks)
847 : {
848 176 : if (OMP_CLAUSE_NUM_TASKS_STRICT (num_tasks))
849 3 : iflags |= GOMP_TASK_FLAG_STRICT;
850 176 : num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
851 : }
852 : else
853 : {
854 1154 : num_tasks = omp_find_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
855 1154 : if (num_tasks)
856 : {
857 220 : iflags |= GOMP_TASK_FLAG_GRAINSIZE;
858 220 : if (OMP_CLAUSE_GRAINSIZE_STRICT (num_tasks))
859 3 : iflags |= GOMP_TASK_FLAG_STRICT;
860 220 : num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
861 : }
862 : else
863 934 : num_tasks = integer_zero_node;
864 : }
865 1330 : num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
866 1330 : if (ifc == NULL_TREE)
867 959 : iflags |= GOMP_TASK_FLAG_IF;
868 1330 : if (omp_find_clause (tclauses, OMP_CLAUSE_NOGROUP))
869 57 : iflags |= GOMP_TASK_FLAG_NOGROUP;
870 1330 : ull = fd.iter_type == long_long_unsigned_type_node;
871 1330 : if (omp_find_clause (clauses, OMP_CLAUSE_REDUCTION))
872 497 : iflags |= GOMP_TASK_FLAG_REDUCTION;
873 : }
874 : else
875 : {
876 2482 : if (priority)
877 18 : iflags |= GOMP_TASK_FLAG_PRIORITY;
878 2482 : if (detach)
879 166 : iflags |= GOMP_TASK_FLAG_DETACH;
880 : }
881 :
882 3812 : tree flags = build_int_cst (unsigned_type_node, iflags);
883 :
884 3812 : tree cond = boolean_true_node;
885 3812 : if (ifc)
886 : {
887 484 : if (taskloop_p)
888 : {
889 371 : tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
890 371 : t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
891 : build_int_cst (unsigned_type_node,
892 : GOMP_TASK_FLAG_IF),
893 : build_int_cst (unsigned_type_node, 0));
894 371 : flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
895 : flags, t);
896 : }
897 : else
898 113 : cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
899 : }
900 :
901 3812 : if (finalc)
902 : {
903 410 : tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
904 410 : t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
905 : build_int_cst (unsigned_type_node,
906 : GOMP_TASK_FLAG_FINAL),
907 : build_int_cst (unsigned_type_node, 0));
908 410 : flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
909 : }
910 3812 : if (depend)
911 1105 : depend = OMP_CLAUSE_DECL (depend);
912 : else
913 2707 : depend = build_int_cst (ptr_type_node, 0);
914 3812 : if (priority)
915 372 : priority = fold_convert (integer_type_node,
916 : OMP_CLAUSE_PRIORITY_EXPR (priority));
917 : else
918 3440 : priority = integer_zero_node;
919 :
920 3812 : gsi = gsi_last_nondebug_bb (bb);
921 :
922 3646 : detach = (detach
923 3978 : ? build_fold_addr_expr (OMP_CLAUSE_DECL (detach))
924 : : null_pointer_node);
925 :
926 3812 : tree t = gimple_omp_task_data_arg (entry_stmt);
927 3812 : if (t == NULL)
928 719 : t2 = null_pointer_node;
929 : else
930 3093 : t2 = build_fold_addr_expr_loc (loc, t);
931 3812 : t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
932 3812 : t = gimple_omp_task_copy_fn (entry_stmt);
933 3812 : if (t == NULL)
934 3308 : t3 = null_pointer_node;
935 : else
936 504 : t3 = build_fold_addr_expr_loc (loc, t);
937 :
938 3812 : if (taskloop_p)
939 2660 : t = build_call_expr (ull
940 42 : ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
941 1288 : : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
942 : 11, t1, t2, t3,
943 : gimple_omp_task_arg_size (entry_stmt),
944 : gimple_omp_task_arg_align (entry_stmt), flags,
945 : num_tasks, priority, startvar, endvar, step);
946 : else
947 2482 : t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
948 : 10, t1, t2, t3,
949 : gimple_omp_task_arg_size (entry_stmt),
950 : gimple_omp_task_arg_align (entry_stmt), cond, flags,
951 : depend, priority, detach);
952 :
953 3812 : force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
954 : false, GSI_CONTINUE_LINKING);
955 3812 : }
956 :
957 : /* Build the function call to GOMP_taskwait_depend to actually
958 : generate the taskwait operation. BB is the block where to insert the
959 : code. */
960 :
961 : static void
962 84 : expand_taskwait_call (basic_block bb, gomp_task *entry_stmt)
963 : {
964 84 : tree clauses = gimple_omp_task_clauses (entry_stmt);
965 84 : tree depend = omp_find_clause (clauses, OMP_CLAUSE_DEPEND);
966 84 : if (depend == NULL_TREE)
967 0 : return;
968 :
969 84 : depend = OMP_CLAUSE_DECL (depend);
970 :
971 84 : bool nowait = omp_find_clause (clauses, OMP_CLAUSE_NOWAIT) != NULL_TREE;
972 84 : gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
973 51 : enum built_in_function f = (nowait
974 84 : ? BUILT_IN_GOMP_TASKWAIT_DEPEND_NOWAIT
975 : : BUILT_IN_GOMP_TASKWAIT_DEPEND);
976 84 : tree t = build_call_expr (builtin_decl_explicit (f), 1, depend);
977 :
978 84 : force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
979 : false, GSI_CONTINUE_LINKING);
980 : }
981 :
982 : /* Build the function call to GOMP_teams_reg to actually
983 : generate the host teams operation. REGION is the teams region
984 : being expanded. BB is the block where to insert the code. */
985 :
986 : static void
987 2572 : expand_teams_call (basic_block bb, gomp_teams *entry_stmt)
988 : {
989 2572 : tree clauses = gimple_omp_teams_clauses (entry_stmt);
990 2572 : tree num_teams = omp_find_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
991 2572 : tree thread_limit = omp_find_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
992 2572 : tree message = omp_find_clause (clauses, OMP_CLAUSE_MESSAGE);
993 2572 : if (message
994 2572 : && ((thread_limit && OMP_CLAUSE_THREAD_LIMIT_STRICT (thread_limit))
995 1 : || (num_teams && (TREE_CODE (num_teams) != INTEGER_CST
996 0 : || tree_int_cst_sgn (num_teams) < 0))))
997 0 : sorry_at (OMP_CLAUSE_LOCATION (message), "%<message%> clause");
998 2572 : if (num_teams == NULL_TREE)
999 2301 : num_teams = build_int_cst (unsigned_type_node, 0);
1000 : else
1001 : {
1002 271 : tree expr = OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (num_teams);
1003 : /* FIXME: Implement lower-bound handling as well; however, currently,
1004 : on the host the use-specified value is always used. */
1005 271 : if (TREE_CODE (expr) == TREE_LIST
1006 28 : && OMP_CLAUSE_NUM_TEAMS_DIMS (num_teams)
1007 275 : && TREE_CHAIN (expr))
1008 : {
1009 1 : sorry_at (OMP_CLAUSE_LOCATION (num_teams),
1010 : "%<num_teams%> clause with %<dims%> modifier");
1011 1 : expr = TREE_VALUE (expr);
1012 : }
1013 270 : else if (TREE_CODE (expr) == TREE_LIST)
1014 27 : expr = (TREE_CHAIN (expr)
1015 27 : ? TREE_VALUE (TREE_CHAIN (expr)) : TREE_VALUE (expr));
1016 271 : num_teams = fold_convert (unsigned_type_node, expr);
1017 : }
1018 2572 : if (thread_limit == NULL_TREE)
1019 2426 : thread_limit = build_int_cst (unsigned_type_node, 0);
1020 : else
1021 : {
1022 146 : tree expr = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
1023 146 : if (TREE_CODE (expr) == TREE_LIST)
1024 : {
1025 15 : if (OMP_CLAUSE_THREAD_LIMIT_DIMS (thread_limit)
1026 15 : && (TREE_CHAIN (expr)
1027 0 : || OMP_CLAUSE_THREAD_LIMIT_STRICT (thread_limit)))
1028 1 : sorry_at (OMP_CLAUSE_LOCATION (thread_limit),
1029 : "%<thread_limit%> clause with %<dims%> modifier");
1030 14 : else if (OMP_CLAUSE_THREAD_LIMIT_STRICT (thread_limit))
1031 0 : sorry_at (OMP_CLAUSE_LOCATION (thread_limit),
1032 : "%<thread_limit%> clause with %<strict%> modifier");
1033 15 : expr = TREE_VALUE (expr);
1034 : }
1035 131 : else if (OMP_CLAUSE_THREAD_LIMIT_STRICT (thread_limit))
1036 0 : sorry_at (OMP_CLAUSE_LOCATION (thread_limit),
1037 : "%<thread_limit%> clause with %<strict%> modifier");
1038 146 : thread_limit = fold_convert (unsigned_type_node, expr);
1039 : }
1040 :
1041 2572 : gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
1042 2572 : tree t = gimple_omp_teams_data_arg (entry_stmt), t1;
1043 2572 : if (t == NULL)
1044 1379 : t1 = null_pointer_node;
1045 : else
1046 1193 : t1 = build_fold_addr_expr (t);
1047 2572 : tree child_fndecl = gimple_omp_teams_child_fn (entry_stmt);
1048 2572 : tree t2 = build_fold_addr_expr (child_fndecl);
1049 :
1050 2572 : vec<tree, va_gc> *args;
1051 2572 : vec_alloc (args, 5);
1052 2572 : args->quick_push (t2);
1053 2572 : args->quick_push (t1);
1054 2572 : args->quick_push (num_teams);
1055 2572 : args->quick_push (thread_limit);
1056 : /* For future extensibility: flags. */
1057 2572 : args->quick_push (build_zero_cst (unsigned_type_node));
1058 :
1059 2572 : t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
1060 : builtin_decl_explicit (BUILT_IN_GOMP_TEAMS_REG),
1061 : args);
1062 :
1063 2572 : force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
1064 : false, GSI_CONTINUE_LINKING);
1065 2572 : }
1066 :
1067 : /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1068 :
1069 : static tree
1070 43969 : vec2chain (vec<tree, va_gc> *v)
1071 : {
1072 43969 : tree chain = NULL_TREE, t;
1073 43969 : unsigned ix;
1074 :
1075 450902 : FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
1076 : {
1077 368510 : DECL_CHAIN (t) = chain;
1078 368510 : chain = t;
1079 : }
1080 :
1081 43969 : return chain;
1082 : }
1083 :
1084 : /* Remove barriers in REGION->EXIT's block. Note that this is only
1085 : valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
1086 : is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
1087 : left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
1088 : removed. */
1089 :
1090 : static void
1091 11879 : remove_exit_barrier (struct omp_region *region)
1092 : {
1093 11879 : gimple_stmt_iterator gsi;
1094 11879 : basic_block exit_bb;
1095 11879 : edge_iterator ei;
1096 11879 : edge e;
1097 11879 : gimple *stmt;
1098 11879 : int any_addressable_vars = -1;
1099 :
1100 11879 : exit_bb = region->exit;
1101 :
1102 : /* If the parallel region doesn't return, we don't have REGION->EXIT
1103 : block at all. */
1104 11879 : if (! exit_bb)
1105 1220 : return;
1106 :
1107 : /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
1108 : workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
1109 : statements that can appear in between are extremely limited -- no
1110 : memory operations at all. Here, we allow nothing at all, so the
1111 : only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
1112 11852 : gsi = gsi_last_nondebug_bb (exit_bb);
1113 11852 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
1114 11852 : gsi_prev_nondebug (&gsi);
1115 11852 : if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
1116 : return;
1117 :
1118 21688 : FOR_EACH_EDGE (e, ei, exit_bb->preds)
1119 : {
1120 11029 : gsi = gsi_last_nondebug_bb (e->src);
1121 11029 : if (gsi_end_p (gsi))
1122 43 : continue;
1123 10986 : stmt = gsi_stmt (gsi);
1124 10986 : if (gimple_code (stmt) == GIMPLE_OMP_RETURN
1125 10986 : && !gimple_omp_return_nowait_p (stmt))
1126 : {
1127 : /* OpenMP 3.0 tasks unfortunately prevent this optimization
1128 : in many cases. If there could be tasks queued, the barrier
1129 : might be needed to let the tasks run before some local
1130 : variable of the parallel that the task uses as shared
1131 : runs out of scope. The task can be spawned either
1132 : from within current function (this would be easy to check)
1133 : or from some function it calls and gets passed an address
1134 : of such a variable. */
1135 1057 : if (any_addressable_vars < 0)
1136 : {
1137 1057 : gomp_parallel *parallel_stmt
1138 1057 : = as_a <gomp_parallel *> (last_nondebug_stmt (region->entry));
1139 1057 : tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
1140 1057 : tree local_decls, block, decl;
1141 1057 : unsigned ix;
1142 :
1143 1057 : any_addressable_vars = 0;
1144 8563 : FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
1145 7063 : if (TREE_ADDRESSABLE (decl))
1146 : {
1147 : any_addressable_vars = 1;
1148 : break;
1149 : }
1150 1058 : for (block = gimple_block (stmt);
1151 1058 : !any_addressable_vars
1152 1058 : && block
1153 1058 : && TREE_CODE (block) == BLOCK;
1154 1 : block = BLOCK_SUPERCONTEXT (block))
1155 : {
1156 2 : for (local_decls = BLOCK_VARS (block);
1157 2 : local_decls;
1158 0 : local_decls = DECL_CHAIN (local_decls))
1159 0 : if (TREE_ADDRESSABLE (local_decls))
1160 : {
1161 : any_addressable_vars = 1;
1162 : break;
1163 : }
1164 2 : if (block == gimple_block (parallel_stmt))
1165 : break;
1166 : }
1167 : }
1168 1057 : if (!any_addressable_vars)
1169 529 : gimple_omp_return_set_nowait (stmt);
1170 : }
1171 : }
1172 : }
1173 :
1174 : static void
1175 68933 : remove_exit_barriers (struct omp_region *region)
1176 : {
1177 68933 : if (region->type == GIMPLE_OMP_PARALLEL)
1178 11879 : remove_exit_barrier (region);
1179 :
1180 68933 : if (region->inner)
1181 : {
1182 37953 : region = region->inner;
1183 37953 : remove_exit_barriers (region);
1184 82183 : while (region->next)
1185 : {
1186 6277 : region = region->next;
1187 6277 : remove_exit_barriers (region);
1188 : }
1189 : }
1190 68933 : }
1191 :
1192 : /* Optimize omp_get_thread_num () and omp_get_num_threads ()
1193 : calls. These can't be declared as const functions, but
1194 : within one parallel body they are constant, so they can be
1195 : transformed there into __builtin_omp_get_{thread_num,num_threads} ()
1196 : which are declared const. Similarly for task body, except
1197 : that in untied task omp_get_thread_num () can change at any task
1198 : scheduling point. */
1199 :
1200 : static void
1201 16911 : optimize_omp_library_calls (gimple *entry_stmt)
1202 : {
1203 16911 : basic_block bb;
1204 16911 : gimple_stmt_iterator gsi;
1205 16911 : tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
1206 16911 : tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
1207 16911 : tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
1208 16911 : tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
1209 16911 : bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
1210 19357 : && omp_find_clause (gimple_omp_task_clauses (entry_stmt),
1211 16911 : OMP_CLAUSE_UNTIED) != NULL);
1212 :
1213 294744 : FOR_EACH_BB_FN (bb, cfun)
1214 1558570 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1215 : {
1216 1002904 : gimple *call = gsi_stmt (gsi);
1217 1002904 : tree decl;
1218 :
1219 1002904 : if (is_gimple_call (call)
1220 75244 : && (decl = gimple_call_fndecl (call))
1221 67924 : && DECL_EXTERNAL (decl)
1222 56202 : && TREE_PUBLIC (decl)
1223 1059106 : && DECL_INITIAL (decl) == NULL)
1224 : {
1225 56201 : tree built_in;
1226 :
1227 56201 : if (DECL_NAME (decl) == thr_num_id)
1228 : {
1229 : /* In #pragma omp task untied omp_get_thread_num () can change
1230 : during the execution of the task region. */
1231 1308 : if (untied_task)
1232 0 : continue;
1233 1308 : built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
1234 : }
1235 54893 : else if (DECL_NAME (decl) == num_thr_id)
1236 412 : built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
1237 : else
1238 54481 : continue;
1239 :
1240 1720 : if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
1241 1720 : || gimple_call_num_args (call) != 0)
1242 1190 : continue;
1243 :
1244 530 : if (flag_exceptions && !TREE_NOTHROW (decl))
1245 0 : continue;
1246 :
1247 530 : if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1248 1060 : || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
1249 530 : TREE_TYPE (TREE_TYPE (built_in))))
1250 0 : continue;
1251 :
1252 530 : gimple_call_set_fndecl (call, built_in);
1253 : }
1254 : }
1255 16911 : }
1256 :
1257 : /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
1258 : regimplified. */
1259 :
1260 : static tree
1261 263563 : expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
1262 : {
1263 263563 : tree t = *tp;
1264 :
1265 : /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
1266 263563 : if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t))
1267 : return t;
1268 :
1269 263467 : if (TREE_CODE (t) == ADDR_EXPR)
1270 1763 : recompute_tree_invariant_for_addr_expr (t);
1271 :
1272 263467 : *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
1273 263467 : return NULL_TREE;
1274 : }
1275 :
1276 : /* Prepend or append TO = FROM assignment before or after *GSI_P. */
1277 :
1278 : static void
1279 64885 : expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
1280 : bool after)
1281 : {
1282 64885 : bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
1283 126277 : from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
1284 : !after, after ? GSI_CONTINUE_LINKING
1285 : : GSI_SAME_STMT);
1286 64885 : gimple *stmt = gimple_build_assign (to, from);
1287 64885 : if (after)
1288 3493 : gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
1289 : else
1290 61392 : gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
1291 64885 : if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
1292 64885 : || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
1293 : {
1294 80 : gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
1295 80 : gimple_regimplify_operands (stmt, &gsi);
1296 : }
1297 64885 : }
1298 :
1299 : /* Prepend or append LHS CODE RHS condition before or after *GSI_P. */
1300 :
1301 : static gcond *
1302 8434 : expand_omp_build_cond (gimple_stmt_iterator *gsi_p, enum tree_code code,
1303 : tree lhs, tree rhs, bool after = false)
1304 : {
1305 8434 : gcond *cond_stmt = gimple_build_cond (code, lhs, rhs, NULL_TREE, NULL_TREE);
1306 8434 : if (after)
1307 236 : gsi_insert_after (gsi_p, cond_stmt, GSI_CONTINUE_LINKING);
1308 : else
1309 8198 : gsi_insert_before (gsi_p, cond_stmt, GSI_SAME_STMT);
1310 8434 : if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
1311 : NULL, NULL)
1312 8434 : || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
1313 : NULL, NULL))
1314 : {
1315 6 : gimple_stmt_iterator gsi = gsi_for_stmt (cond_stmt);
1316 6 : gimple_regimplify_operands (cond_stmt, &gsi);
1317 : }
1318 8434 : return cond_stmt;
1319 : }
1320 :
1321 : /* Expand the OpenMP parallel or task directive starting at REGION. */
1322 :
1323 : static void
1324 22868 : expand_omp_taskreg (struct omp_region *region)
1325 : {
1326 22868 : basic_block entry_bb, exit_bb, new_bb;
1327 22868 : struct function *child_cfun;
1328 22868 : tree child_fn, block, t;
1329 22868 : gimple_stmt_iterator gsi;
1330 22868 : gimple *entry_stmt, *stmt;
1331 22868 : edge e;
1332 22868 : vec<tree, va_gc> *ws_args;
1333 :
1334 22868 : entry_stmt = last_nondebug_stmt (region->entry);
1335 22868 : if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
1336 22868 : && gimple_omp_task_taskwait_p (entry_stmt))
1337 : {
1338 84 : new_bb = region->entry;
1339 84 : gsi = gsi_last_nondebug_bb (region->entry);
1340 84 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
1341 84 : gsi_remove (&gsi, true);
1342 84 : expand_taskwait_call (new_bb, as_a <gomp_task *> (entry_stmt));
1343 84 : return;
1344 : }
1345 :
1346 22784 : child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
1347 22784 : child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1348 :
1349 22784 : entry_bb = region->entry;
1350 22784 : if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
1351 3812 : exit_bb = region->cont;
1352 : else
1353 18972 : exit_bb = region->exit;
1354 :
1355 22784 : if (is_combined_parallel (region))
1356 1200 : ws_args = region->ws_args;
1357 : else
1358 : ws_args = NULL;
1359 :
1360 22784 : if (child_cfun->cfg)
1361 : {
1362 : /* Due to inlining, it may happen that we have already outlined
1363 : the region, in which case all we need to do is make the
1364 : sub-graph unreachable and emit the parallel call. */
1365 0 : edge entry_succ_e, exit_succ_e;
1366 :
1367 0 : entry_succ_e = single_succ_edge (entry_bb);
1368 :
1369 0 : gsi = gsi_last_nondebug_bb (entry_bb);
1370 0 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
1371 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK
1372 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TEAMS);
1373 0 : gsi_remove (&gsi, true);
1374 :
1375 0 : new_bb = entry_bb;
1376 0 : if (exit_bb)
1377 : {
1378 0 : exit_succ_e = single_succ_edge (exit_bb);
1379 0 : make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
1380 : }
1381 0 : remove_edge_and_dominated_blocks (entry_succ_e);
1382 : }
1383 : else
1384 : {
1385 22784 : unsigned srcidx, dstidx, num;
1386 :
1387 : /* If the parallel region needs data sent from the parent
1388 : function, then the very first statement (except possible
1389 : tree profile counter updates) of the parallel body
1390 : is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
1391 : &.OMP_DATA_O is passed as an argument to the child function,
1392 : we need to replace it with the argument as seen by the child
1393 : function.
1394 :
1395 : In most cases, this will end up being the identity assignment
1396 : .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
1397 : a function call that has been inlined, the original PARM_DECL
1398 : .OMP_DATA_I may have been converted into a different local
1399 : variable. In which case, we need to keep the assignment. */
1400 22784 : if (gimple_omp_taskreg_data_arg (entry_stmt))
1401 : {
1402 18273 : basic_block entry_succ_bb
1403 33453 : = single_succ_p (entry_bb) ? single_succ (entry_bb)
1404 3093 : : FALLTHRU_EDGE (entry_bb)->dest;
1405 18273 : tree arg;
1406 18273 : gimple *parcopy_stmt = NULL;
1407 :
1408 36546 : for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
1409 : {
1410 18273 : gimple *stmt;
1411 :
1412 18273 : gcc_assert (!gsi_end_p (gsi));
1413 18273 : stmt = gsi_stmt (gsi);
1414 18273 : if (gimple_code (stmt) != GIMPLE_ASSIGN)
1415 0 : continue;
1416 :
1417 18273 : if (gimple_num_ops (stmt) == 2)
1418 : {
1419 18273 : tree arg = gimple_assign_rhs1 (stmt);
1420 :
1421 : /* We're ignore the subcode because we're
1422 : effectively doing a STRIP_NOPS. */
1423 :
1424 18273 : if (TREE_CODE (arg) == ADDR_EXPR
1425 18273 : && (TREE_OPERAND (arg, 0)
1426 18273 : == gimple_omp_taskreg_data_arg (entry_stmt)))
1427 : {
1428 18273 : parcopy_stmt = stmt;
1429 18273 : break;
1430 : }
1431 : }
1432 0 : }
1433 :
1434 18273 : gcc_assert (parcopy_stmt != NULL);
1435 18273 : arg = DECL_ARGUMENTS (child_fn);
1436 :
1437 18273 : if (!gimple_in_ssa_p (cfun))
1438 : {
1439 18090 : if (gimple_assign_lhs (parcopy_stmt) == arg)
1440 18090 : gsi_remove (&gsi, true);
1441 : else
1442 : {
1443 : /* ?? Is setting the subcode really necessary ?? */
1444 0 : gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
1445 0 : gimple_assign_set_rhs1 (parcopy_stmt, arg);
1446 : }
1447 : }
1448 : else
1449 : {
1450 183 : tree lhs = gimple_assign_lhs (parcopy_stmt);
1451 183 : gcc_assert (SSA_NAME_VAR (lhs) == arg);
1452 : /* We'd like to set the rhs to the default def in the child_fn,
1453 : but it's too early to create ssa names in the child_fn.
1454 : Instead, we set the rhs to the parm. In
1455 : move_sese_region_to_fn, we introduce a default def for the
1456 : parm, map the parm to it's default def, and once we encounter
1457 : this stmt, replace the parm with the default def. */
1458 183 : gimple_assign_set_rhs1 (parcopy_stmt, arg);
1459 183 : update_stmt (parcopy_stmt);
1460 : }
1461 : }
1462 :
1463 : /* Declare local variables needed in CHILD_CFUN. */
1464 22784 : block = DECL_INITIAL (child_fn);
1465 22784 : BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
1466 : /* The gimplifier could record temporaries in parallel/task block
1467 : rather than in containing function's local_decls chain,
1468 : which would mean cgraph missed finalizing them. Do it now. */
1469 254071 : for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
1470 231287 : if (VAR_P (t) && TREE_STATIC (t) && !DECL_EXTERNAL (t))
1471 1 : varpool_node::finalize_decl (t);
1472 22784 : DECL_SAVED_TREE (child_fn) = NULL;
1473 : /* We'll create a CFG for child_fn, so no gimple body is needed. */
1474 22784 : gimple_set_body (child_fn, NULL);
1475 22784 : TREE_USED (block) = 1;
1476 :
1477 : /* Reset DECL_CONTEXT on function arguments. */
1478 45568 : for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
1479 22784 : DECL_CONTEXT (t) = child_fn;
1480 :
1481 : /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
1482 : so that it can be moved to the child function. */
1483 22784 : gsi = gsi_last_nondebug_bb (entry_bb);
1484 22784 : stmt = gsi_stmt (gsi);
1485 22784 : gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
1486 : || gimple_code (stmt) == GIMPLE_OMP_TASK
1487 : || gimple_code (stmt) == GIMPLE_OMP_TEAMS));
1488 22784 : e = split_block (entry_bb, stmt);
1489 22784 : gsi_remove (&gsi, true);
1490 22784 : entry_bb = e->dest;
1491 22784 : edge e2 = NULL;
1492 22784 : if (gimple_code (entry_stmt) != GIMPLE_OMP_TASK)
1493 18972 : single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
1494 : else
1495 : {
1496 3812 : e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
1497 3812 : gcc_assert (e2->dest == region->exit);
1498 3812 : remove_edge (BRANCH_EDGE (entry_bb));
1499 3812 : set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
1500 3812 : gsi = gsi_last_nondebug_bb (region->exit);
1501 3812 : gcc_assert (!gsi_end_p (gsi)
1502 : && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
1503 3812 : gsi_remove (&gsi, true);
1504 : }
1505 :
1506 : /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
1507 22784 : if (exit_bb)
1508 : {
1509 22740 : gsi = gsi_last_nondebug_bb (exit_bb);
1510 41685 : gcc_assert (!gsi_end_p (gsi)
1511 : && (gimple_code (gsi_stmt (gsi))
1512 : == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
1513 22740 : stmt = gimple_build_return (NULL);
1514 22740 : gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
1515 22740 : gsi_remove (&gsi, true);
1516 : }
1517 :
1518 : /* Move the parallel region into CHILD_CFUN. */
1519 :
1520 22784 : if (gimple_in_ssa_p (cfun))
1521 : {
1522 195 : init_tree_ssa (child_cfun);
1523 195 : init_ssa_operands (child_cfun);
1524 195 : child_cfun->gimple_df->in_ssa_p = true;
1525 195 : block = NULL_TREE;
1526 : }
1527 : else
1528 22589 : block = gimple_block (entry_stmt);
1529 :
1530 22784 : new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
1531 22784 : if (exit_bb)
1532 22740 : single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
1533 22784 : if (e2)
1534 : {
1535 3812 : basic_block dest_bb = e2->dest;
1536 3812 : if (!exit_bb)
1537 17 : make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
1538 3812 : remove_edge (e2);
1539 3812 : set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
1540 : }
1541 : /* When the OMP expansion process cannot guarantee an up-to-date
1542 : loop tree arrange for the child function to fixup loops. */
1543 22784 : if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
1544 22589 : child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
1545 :
1546 : /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
1547 22784 : num = vec_safe_length (child_cfun->local_decls);
1548 1077179 : for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
1549 : {
1550 1054395 : t = (*child_cfun->local_decls)[srcidx];
1551 1054395 : if (DECL_CONTEXT (t) == cfun->decl)
1552 231287 : continue;
1553 823108 : if (srcidx != dstidx)
1554 819261 : (*child_cfun->local_decls)[dstidx] = t;
1555 823108 : dstidx++;
1556 : }
1557 22784 : if (dstidx != num)
1558 20588 : vec_safe_truncate (child_cfun->local_decls, dstidx);
1559 :
1560 : /* Inform the callgraph about the new function. */
1561 22784 : child_cfun->curr_properties = cfun->curr_properties;
1562 22784 : child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
1563 22784 : child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
1564 22784 : cgraph_node *node = cgraph_node::get_create (child_fn);
1565 22784 : node->parallelized_function = 1;
1566 45568 : node->has_omp_variant_constructs
1567 22784 : |= cgraph_node::get (cfun->decl)->has_omp_variant_constructs;
1568 22784 : cgraph_node::add_new_function (child_fn, true);
1569 :
1570 22784 : bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
1571 22784 : && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
1572 :
1573 : /* Fix the callgraph edges for child_cfun. Those for cfun will be
1574 : fixed in a following pass. */
1575 22784 : push_cfun (child_cfun);
1576 22784 : if (need_asm)
1577 22589 : assign_assembler_name_if_needed (child_fn);
1578 :
1579 22784 : if (optimize)
1580 16911 : optimize_omp_library_calls (entry_stmt);
1581 22784 : update_max_bb_count ();
1582 22784 : cgraph_edge::rebuild_edges ();
1583 :
1584 : /* Some EH regions might become dead, see PR34608. If
1585 : pass_cleanup_cfg isn't the first pass to happen with the
1586 : new child, these dead EH edges might cause problems.
1587 : Clean them up now. */
1588 22784 : if (flag_exceptions)
1589 : {
1590 10289 : basic_block bb;
1591 10289 : bool changed = false;
1592 :
1593 136412 : FOR_EACH_BB_FN (bb, cfun)
1594 126123 : changed |= gimple_purge_dead_eh_edges (bb);
1595 10289 : if (changed)
1596 0 : cleanup_tree_cfg ();
1597 : }
1598 22784 : if (gimple_in_ssa_p (cfun))
1599 195 : update_ssa (TODO_update_ssa);
1600 22784 : if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
1601 195 : verify_loop_structure ();
1602 22784 : pop_cfun ();
1603 :
1604 22784 : if (dump_file && !gimple_in_ssa_p (cfun))
1605 : {
1606 88 : omp_any_child_fn_dumped = true;
1607 88 : dump_function_header (dump_file, child_fn, dump_flags);
1608 88 : dump_function_to_file (child_fn, dump_file, dump_flags);
1609 : }
1610 : }
1611 :
1612 22784 : adjust_context_and_scope (region, gimple_block (entry_stmt), child_fn);
1613 :
1614 22784 : if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1615 16400 : expand_parallel_call (region, new_bb,
1616 : as_a <gomp_parallel *> (entry_stmt), ws_args);
1617 6384 : else if (gimple_code (entry_stmt) == GIMPLE_OMP_TEAMS)
1618 2572 : expand_teams_call (new_bb, as_a <gomp_teams *> (entry_stmt));
1619 : else
1620 3812 : expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
1621 : }
1622 :
1623 : /* Information about members of an OpenACC collapsed loop nest. */
1624 :
1625 : struct oacc_collapse
1626 : {
1627 : tree base; /* Base value. */
1628 : tree iters; /* Number of steps. */
1629 : tree step; /* Step size. */
1630 : tree tile; /* Tile increment (if tiled). */
1631 : tree outer; /* Tile iterator var. */
1632 : };
1633 :
1634 : /* Helper for expand_oacc_for. Determine collapsed loop information.
1635 : Fill in COUNTS array. Emit any initialization code before GSI.
1636 : Return the calculated outer loop bound of BOUND_TYPE. */
1637 :
1638 : static tree
1639 594 : expand_oacc_collapse_init (const struct omp_for_data *fd,
1640 : gimple_stmt_iterator *gsi,
1641 : oacc_collapse *counts, tree diff_type,
1642 : tree bound_type, location_t loc)
1643 : {
1644 594 : tree tiling = fd->tiling;
1645 594 : tree total = build_int_cst (bound_type, 1);
1646 594 : int ix;
1647 :
1648 594 : gcc_assert (integer_onep (fd->loop.step));
1649 594 : gcc_assert (integer_zerop (fd->loop.n1));
1650 :
1651 : /* When tiling, the first operand of the tile clause applies to the
1652 : innermost loop, and we work outwards from there. Seems
1653 : backwards, but whatever. */
1654 1890 : for (ix = fd->collapse; ix--;)
1655 : {
1656 1296 : const omp_for_data_loop *loop = &fd->loops[ix];
1657 :
1658 1296 : tree iter_type = TREE_TYPE (loop->v);
1659 1296 : tree plus_type = iter_type;
1660 :
1661 1296 : gcc_assert (loop->cond_code == LT_EXPR || loop->cond_code == GT_EXPR);
1662 :
1663 1296 : if (POINTER_TYPE_P (iter_type))
1664 0 : plus_type = sizetype;
1665 :
1666 1296 : if (tiling)
1667 : {
1668 284 : tree num = build_int_cst (integer_type_node, fd->collapse);
1669 284 : tree loop_no = build_int_cst (integer_type_node, ix);
1670 284 : tree tile = TREE_VALUE (tiling);
1671 284 : gcall *call
1672 284 : = gimple_build_call_internal (IFN_GOACC_TILE, 5, num, loop_no, tile,
1673 : /* gwv-outer=*/integer_zero_node,
1674 : /* gwv-inner=*/integer_zero_node);
1675 :
1676 284 : counts[ix].outer = create_tmp_var (iter_type, ".outer");
1677 284 : counts[ix].tile = create_tmp_var (diff_type, ".tile");
1678 284 : gimple_call_set_lhs (call, counts[ix].tile);
1679 284 : gimple_set_location (call, loc);
1680 284 : gsi_insert_before (gsi, call, GSI_SAME_STMT);
1681 :
1682 284 : tiling = TREE_CHAIN (tiling);
1683 : }
1684 : else
1685 : {
1686 1012 : counts[ix].tile = NULL;
1687 1012 : counts[ix].outer = loop->v;
1688 : }
1689 :
1690 1296 : tree b = loop->n1;
1691 1296 : tree e = loop->n2;
1692 1296 : tree s = loop->step;
1693 1296 : bool up = loop->cond_code == LT_EXPR;
1694 1344 : tree dir = build_int_cst (diff_type, up ? +1 : -1);
1695 1296 : bool negating;
1696 1296 : tree expr;
1697 :
1698 1296 : b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
1699 : true, GSI_SAME_STMT);
1700 1296 : e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
1701 : true, GSI_SAME_STMT);
1702 :
1703 : /* Convert the step, avoiding possible unsigned->signed overflow. */
1704 1296 : negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
1705 0 : if (negating)
1706 0 : s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
1707 1296 : s = fold_convert (diff_type, s);
1708 1296 : if (negating)
1709 0 : s = fold_build1 (NEGATE_EXPR, diff_type, s);
1710 1296 : s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
1711 : true, GSI_SAME_STMT);
1712 :
1713 : /* Determine the range, avoiding possible unsigned->signed overflow. */
1714 1296 : negating = !up && TYPE_UNSIGNED (iter_type);
1715 2592 : expr = fold_build2 (MINUS_EXPR, plus_type,
1716 : fold_convert (plus_type, negating ? b : e),
1717 : fold_convert (plus_type, negating ? e : b));
1718 1296 : expr = fold_convert (diff_type, expr);
1719 1296 : if (negating)
1720 0 : expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
1721 1296 : tree range = force_gimple_operand_gsi
1722 1296 : (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
1723 :
1724 : /* Determine number of iterations. */
1725 1296 : expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
1726 1296 : expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
1727 1296 : expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
1728 :
1729 1296 : tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
1730 : true, GSI_SAME_STMT);
1731 :
1732 1296 : counts[ix].base = b;
1733 1296 : counts[ix].iters = iters;
1734 1296 : counts[ix].step = s;
1735 :
1736 1296 : total = fold_build2 (MULT_EXPR, bound_type, total,
1737 : fold_convert (bound_type, iters));
1738 : }
1739 :
1740 594 : return total;
1741 : }
1742 :
1743 : /* Emit initializers for collapsed loop members. INNER is true if
1744 : this is for the element loop of a TILE. IVAR is the outer
1745 : loop iteration variable, from which collapsed loop iteration values
1746 : are calculated. COUNTS array has been initialized by
1747 : expand_oacc_collapse_inits. */
1748 :
1749 : static void
1750 771 : expand_oacc_collapse_vars (const struct omp_for_data *fd, bool inner,
1751 : gimple_stmt_iterator *gsi,
1752 : const oacc_collapse *counts, tree ivar,
1753 : tree diff_type)
1754 : {
1755 771 : tree ivar_type = TREE_TYPE (ivar);
1756 :
1757 : /* The most rapidly changing iteration variable is the innermost
1758 : one. */
1759 2351 : for (int ix = fd->collapse; ix--;)
1760 : {
1761 1580 : const omp_for_data_loop *loop = &fd->loops[ix];
1762 1580 : const oacc_collapse *collapse = &counts[ix];
1763 1580 : tree v = inner ? loop->v : collapse->outer;
1764 1580 : tree iter_type = TREE_TYPE (v);
1765 1580 : tree plus_type = iter_type;
1766 1580 : enum tree_code plus_code = PLUS_EXPR;
1767 1580 : tree expr;
1768 :
1769 1580 : if (POINTER_TYPE_P (iter_type))
1770 : {
1771 0 : plus_code = POINTER_PLUS_EXPR;
1772 0 : plus_type = sizetype;
1773 : }
1774 :
1775 1580 : expr = ivar;
1776 1580 : if (ix)
1777 : {
1778 809 : tree mod = fold_convert (ivar_type, collapse->iters);
1779 809 : ivar = fold_build2 (TRUNC_DIV_EXPR, ivar_type, expr, mod);
1780 809 : expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, expr, mod);
1781 809 : ivar = force_gimple_operand_gsi (gsi, ivar, true, NULL_TREE,
1782 : true, GSI_SAME_STMT);
1783 : }
1784 :
1785 1580 : expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
1786 : fold_convert (diff_type, collapse->step));
1787 1580 : expr = fold_build2 (plus_code, iter_type,
1788 : inner ? collapse->outer : collapse->base,
1789 : fold_convert (plus_type, expr));
1790 1580 : expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
1791 : true, GSI_SAME_STMT);
1792 1580 : gassign *ass = gimple_build_assign (v, expr);
1793 1580 : gsi_insert_before (gsi, ass, GSI_SAME_STMT);
1794 : }
1795 771 : }
1796 :
1797 : /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
1798 : of the combined collapse > 1 loop constructs, generate code like:
1799 : if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
1800 : if (cond3 is <)
1801 : adj = STEP3 - 1;
1802 : else
1803 : adj = STEP3 + 1;
1804 : count3 = (adj + N32 - N31) / STEP3;
1805 : if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
1806 : if (cond2 is <)
1807 : adj = STEP2 - 1;
1808 : else
1809 : adj = STEP2 + 1;
1810 : count2 = (adj + N22 - N21) / STEP2;
1811 : if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
1812 : if (cond1 is <)
1813 : adj = STEP1 - 1;
1814 : else
1815 : adj = STEP1 + 1;
1816 : count1 = (adj + N12 - N11) / STEP1;
1817 : count = count1 * count2 * count3;
1818 : Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
1819 : count = 0;
1820 : and set ZERO_ITER_BB to that bb. If this isn't the outermost
1821 : of the combined loop constructs, just initialize COUNTS array
1822 : from the _looptemp_ clauses. For loop nests with non-rectangular
1823 : loops, do this only for the rectangular loops. Then pick
1824 : the loops which reference outer vars in their bound expressions
1825 : and the loops which they refer to and for this sub-nest compute
1826 : number of iterations. For triangular loops use Faulhaber's formula,
1827 : otherwise as a fallback, compute by iterating the loops.
1828 : If e.g. the sub-nest is
1829 : for (I = N11; I COND1 N12; I += STEP1)
1830 : for (J = M21 * I + N21; J COND2 M22 * I + N22; J += STEP2)
1831 : for (K = M31 * J + N31; K COND3 M32 * J + N32; K += STEP3)
1832 : do:
1833 : COUNT = 0;
1834 : for (tmpi = N11; tmpi COND1 N12; tmpi += STEP1)
1835 : for (tmpj = M21 * tmpi + N21;
1836 : tmpj COND2 M22 * tmpi + N22; tmpj += STEP2)
1837 : {
1838 : int tmpk1 = M31 * tmpj + N31;
1839 : int tmpk2 = M32 * tmpj + N32;
1840 : if (tmpk1 COND3 tmpk2)
1841 : {
1842 : if (COND3 is <)
1843 : adj = STEP3 - 1;
1844 : else
1845 : adj = STEP3 + 1;
1846 : COUNT += (adj + tmpk2 - tmpk1) / STEP3;
1847 : }
1848 : }
1849 : and finally multiply the counts of the rectangular loops not
1850 : in the sub-nest with COUNT. Also, as counts[fd->last_nonrect]
1851 : store number of iterations of the loops from fd->first_nonrect
1852 : to fd->last_nonrect inclusive, i.e. the above COUNT multiplied
1853 : by the counts of rectangular loops not referenced in any non-rectangular
1854 : loops sandwiched in between those. */
1855 :
1856 : /* NOTE: It *could* be better to moosh all of the BBs together,
1857 : creating one larger BB with all the computation and the unexpected
1858 : jump at the end. I.e.
1859 :
1860 : bool zero3, zero2, zero1, zero;
1861 :
1862 : zero3 = N32 c3 N31;
1863 : count3 = (N32 - N31) /[cl] STEP3;
1864 : zero2 = N22 c2 N21;
1865 : count2 = (N22 - N21) /[cl] STEP2;
1866 : zero1 = N12 c1 N11;
1867 : count1 = (N12 - N11) /[cl] STEP1;
1868 : zero = zero3 || zero2 || zero1;
1869 : count = count1 * count2 * count3;
1870 : if (__builtin_expect(zero, false)) goto zero_iter_bb;
1871 :
1872 : After all, we expect the zero=false, and thus we expect to have to
1873 : evaluate all of the comparison expressions, so short-circuiting
1874 : oughtn't be a win. Since the condition isn't protecting a
1875 : denominator, we're not concerned about divide-by-zero, so we can
1876 : fully evaluate count even if a numerator turned out to be wrong.
1877 :
1878 : It seems like putting this all together would create much better
1879 : scheduling opportunities, and less pressure on the chip's branch
1880 : predictor. */
1881 :
1882 : static void
1883 10461 : expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
1884 : basic_block &entry_bb, tree *counts,
1885 : basic_block &zero_iter1_bb, int &first_zero_iter1,
1886 : basic_block &zero_iter2_bb, int &first_zero_iter2,
1887 : basic_block &l2_dom_bb)
1888 : {
1889 10461 : tree t, type = TREE_TYPE (fd->loop.v);
1890 10461 : edge e, ne;
1891 10461 : int i;
1892 :
1893 : /* Collapsed loops need work for expansion into SSA form. */
1894 10461 : gcc_assert (!gimple_in_ssa_p (cfun));
1895 :
1896 10461 : if (gimple_omp_for_combined_into_p (fd->for_stmt)
1897 10461 : && TREE_CODE (fd->loop.n2) != INTEGER_CST)
1898 : {
1899 2692 : gcc_assert (fd->ordered == 0);
1900 : /* First two _looptemp_ clauses are for istart/iend, counts[0]
1901 : isn't supposed to be handled, as the inner loop doesn't
1902 : use it. */
1903 2692 : tree innerc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
1904 : OMP_CLAUSE__LOOPTEMP_);
1905 2692 : gcc_assert (innerc);
1906 10553 : for (i = 0; i < fd->collapse; i++)
1907 : {
1908 7861 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
1909 : OMP_CLAUSE__LOOPTEMP_);
1910 7861 : gcc_assert (innerc);
1911 7861 : if (i)
1912 5169 : counts[i] = OMP_CLAUSE_DECL (innerc);
1913 : else
1914 2692 : counts[0] = NULL_TREE;
1915 : }
1916 2692 : if (fd->non_rect
1917 112 : && fd->last_nonrect == fd->first_nonrect + 1
1918 2756 : && !TYPE_UNSIGNED (TREE_TYPE (fd->loops[fd->last_nonrect].v)))
1919 : {
1920 : tree c[4];
1921 300 : for (i = 0; i < 4; i++)
1922 : {
1923 240 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
1924 : OMP_CLAUSE__LOOPTEMP_);
1925 240 : gcc_assert (innerc);
1926 240 : c[i] = OMP_CLAUSE_DECL (innerc);
1927 : }
1928 60 : counts[0] = c[0];
1929 60 : fd->first_inner_iterations = c[1];
1930 60 : fd->factor = c[2];
1931 60 : fd->adjn1 = c[3];
1932 : }
1933 : return;
1934 : }
1935 :
1936 8662 : for (i = fd->collapse; i < fd->ordered; i++)
1937 : {
1938 893 : tree itype = TREE_TYPE (fd->loops[i].v);
1939 893 : counts[i] = NULL_TREE;
1940 893 : t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
1941 : fold_convert (itype, fd->loops[i].n1),
1942 : fold_convert (itype, fd->loops[i].n2));
1943 893 : if (t && integer_zerop (t))
1944 : {
1945 0 : for (i = fd->collapse; i < fd->ordered; i++)
1946 0 : counts[i] = build_int_cst (type, 0);
1947 : break;
1948 : }
1949 : }
1950 7769 : bool rect_count_seen = false;
1951 7769 : bool init_n2 = SSA_VAR_P (fd->loop.n2) && zero_iter1_bb;
1952 30153 : for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
1953 : {
1954 22384 : tree itype = TREE_TYPE (fd->loops[i].v);
1955 :
1956 22384 : if (i >= fd->collapse && counts[i])
1957 0 : continue;
1958 22384 : if (fd->non_rect)
1959 : {
1960 : /* Skip loops that use outer iterators in their expressions
1961 : during this phase. */
1962 1050 : if (fd->loops[i].m1 || fd->loops[i].m2)
1963 : {
1964 432 : counts[i] = build_zero_cst (type);
1965 432 : continue;
1966 : }
1967 : }
1968 21952 : if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
1969 9514 : && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
1970 : fold_convert (itype, fd->loops[i].n1),
1971 : fold_convert (itype, fd->loops[i].n2)))
1972 5909 : == NULL_TREE || !integer_onep (t)))
1973 : {
1974 5789 : gcond *cond_stmt;
1975 5789 : tree n1, n2;
1976 5789 : if (init_n2 && i < fd->collapse && !rect_count_seen)
1977 : {
1978 : /* When called with non-NULL zero_iter1_bb, we won't clear
1979 : fd->loop.n2 in the if (zero_iter_bb == NULL) code below
1980 : and if it is prior to storing fd->loop.n2 where
1981 : rect_count_seen is set, it could be used uninitialized.
1982 : As zero_iter1_bb in that case can be reached also if there
1983 : are non-zero iterations, the clearing can't be emitted
1984 : to the zero_iter1_bb, but needs to be done before the
1985 : condition. */
1986 1505 : gassign *assign_stmt
1987 1505 : = gimple_build_assign (fd->loop.n2, build_zero_cst (type));
1988 1505 : gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
1989 1505 : init_n2 = false;
1990 : }
1991 5789 : n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
1992 5789 : n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
1993 : true, GSI_SAME_STMT);
1994 5789 : n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
1995 5789 : n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
1996 : true, GSI_SAME_STMT);
1997 5789 : cond_stmt = expand_omp_build_cond (gsi, fd->loops[i].cond_code,
1998 : n1, n2);
1999 5789 : e = split_block (entry_bb, cond_stmt);
2000 216 : basic_block &zero_iter_bb
2001 5789 : = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
2002 216 : int &first_zero_iter
2003 5789 : = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
2004 5789 : if (zero_iter_bb == NULL)
2005 : {
2006 626 : gassign *assign_stmt;
2007 626 : first_zero_iter = i;
2008 626 : zero_iter_bb = create_empty_bb (entry_bb);
2009 626 : add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
2010 626 : *gsi = gsi_after_labels (zero_iter_bb);
2011 626 : if (i < fd->collapse)
2012 508 : assign_stmt = gimple_build_assign (fd->loop.n2,
2013 : build_zero_cst (type));
2014 : else
2015 : {
2016 118 : counts[i] = create_tmp_reg (type, ".count");
2017 118 : assign_stmt
2018 118 : = gimple_build_assign (counts[i], build_zero_cst (type));
2019 : }
2020 626 : gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
2021 626 : set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
2022 : entry_bb);
2023 : }
2024 5789 : ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
2025 5789 : ne->probability = profile_probability::very_unlikely ();
2026 5789 : e->flags = EDGE_TRUE_VALUE;
2027 5789 : e->probability = ne->probability.invert ();
2028 5789 : if (l2_dom_bb == NULL)
2029 2591 : l2_dom_bb = entry_bb;
2030 5789 : entry_bb = e->dest;
2031 5789 : *gsi = gsi_last_nondebug_bb (entry_bb);
2032 : }
2033 :
2034 21952 : if (POINTER_TYPE_P (itype))
2035 1661 : itype = signed_type_for (itype);
2036 21952 : t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
2037 27056 : ? -1 : 1));
2038 21952 : t = fold_build2 (PLUS_EXPR, itype,
2039 : fold_convert (itype, fd->loops[i].step), t);
2040 21952 : t = fold_build2 (PLUS_EXPR, itype, t,
2041 : fold_convert (itype, fd->loops[i].n2));
2042 21952 : t = fold_build2 (MINUS_EXPR, itype, t,
2043 : fold_convert (itype, fd->loops[i].n1));
2044 : /* ?? We could probably use CEIL_DIV_EXPR instead of
2045 : TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
2046 : generate the same code in the end because generically we
2047 : don't know that the values involved must be negative for
2048 : GT?? */
2049 21952 : if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
2050 2248 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
2051 : fold_build1 (NEGATE_EXPR, itype, t),
2052 : fold_build1 (NEGATE_EXPR, itype,
2053 : fold_convert (itype,
2054 : fd->loops[i].step)));
2055 : else
2056 19704 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
2057 : fold_convert (itype, fd->loops[i].step));
2058 21952 : t = fold_convert (type, t);
2059 21952 : if (TREE_CODE (t) == INTEGER_CST)
2060 16093 : counts[i] = t;
2061 : else
2062 : {
2063 5859 : if (i < fd->collapse || i != first_zero_iter2)
2064 5741 : counts[i] = create_tmp_reg (type, ".count");
2065 5859 : expand_omp_build_assign (gsi, counts[i], t);
2066 : }
2067 21952 : if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
2068 : {
2069 8621 : if (fd->non_rect && i >= fd->first_nonrect && i <= fd->last_nonrect)
2070 376 : continue;
2071 8245 : if (!rect_count_seen)
2072 : {
2073 2995 : t = counts[i];
2074 2995 : rect_count_seen = true;
2075 : }
2076 : else
2077 5250 : t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
2078 8245 : expand_omp_build_assign (gsi, fd->loop.n2, t);
2079 : }
2080 : }
2081 7769 : if (fd->non_rect && SSA_VAR_P (fd->loop.n2))
2082 : {
2083 284 : gcc_assert (fd->last_nonrect != -1);
2084 :
2085 284 : counts[fd->last_nonrect] = create_tmp_reg (type, ".count");
2086 284 : expand_omp_build_assign (gsi, counts[fd->last_nonrect],
2087 : build_zero_cst (type));
2088 366 : for (i = fd->first_nonrect + 1; i < fd->last_nonrect; i++)
2089 113 : if (fd->loops[i].m1
2090 83 : || fd->loops[i].m2
2091 82 : || fd->loops[i].non_rect_referenced)
2092 : break;
2093 284 : if (i == fd->last_nonrect
2094 253 : && fd->loops[i].outer == fd->last_nonrect - fd->first_nonrect
2095 253 : && !POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
2096 511 : && !TYPE_UNSIGNED (TREE_TYPE (fd->loops[i].v)))
2097 : {
2098 225 : int o = fd->first_nonrect;
2099 225 : tree itype = TREE_TYPE (fd->loops[o].v);
2100 225 : tree n1o = create_tmp_reg (itype, ".n1o");
2101 225 : t = fold_convert (itype, unshare_expr (fd->loops[o].n1));
2102 225 : expand_omp_build_assign (gsi, n1o, t);
2103 225 : tree n2o = create_tmp_reg (itype, ".n2o");
2104 225 : t = fold_convert (itype, unshare_expr (fd->loops[o].n2));
2105 225 : expand_omp_build_assign (gsi, n2o, t);
2106 225 : if (fd->loops[i].m1 && fd->loops[i].m2)
2107 43 : t = fold_build2 (MINUS_EXPR, itype, unshare_expr (fd->loops[i].m2),
2108 : unshare_expr (fd->loops[i].m1));
2109 182 : else if (fd->loops[i].m1)
2110 162 : t = fold_build1 (NEGATE_EXPR, itype,
2111 : unshare_expr (fd->loops[i].m1));
2112 : else
2113 20 : t = unshare_expr (fd->loops[i].m2);
2114 225 : tree m2minusm1
2115 225 : = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
2116 : true, GSI_SAME_STMT);
2117 :
2118 225 : gimple_stmt_iterator gsi2 = *gsi;
2119 225 : gsi_prev (&gsi2);
2120 225 : e = split_block (entry_bb, gsi_stmt (gsi2));
2121 225 : e = split_block (e->dest, (gimple *) NULL);
2122 225 : basic_block bb1 = e->src;
2123 225 : entry_bb = e->dest;
2124 225 : *gsi = gsi_after_labels (entry_bb);
2125 :
2126 225 : gsi2 = gsi_after_labels (bb1);
2127 225 : tree ostep = fold_convert (itype, fd->loops[o].step);
2128 225 : t = build_int_cst (itype, (fd->loops[o].cond_code
2129 241 : == LT_EXPR ? -1 : 1));
2130 225 : t = fold_build2 (PLUS_EXPR, itype, ostep, t);
2131 225 : t = fold_build2 (PLUS_EXPR, itype, t, n2o);
2132 225 : t = fold_build2 (MINUS_EXPR, itype, t, n1o);
2133 225 : if (TYPE_UNSIGNED (itype)
2134 225 : && fd->loops[o].cond_code == GT_EXPR)
2135 0 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
2136 : fold_build1 (NEGATE_EXPR, itype, t),
2137 : fold_build1 (NEGATE_EXPR, itype, ostep));
2138 : else
2139 225 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, ostep);
2140 225 : tree outer_niters
2141 225 : = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
2142 : true, GSI_SAME_STMT);
2143 225 : t = fold_build2 (MINUS_EXPR, itype, outer_niters,
2144 : build_one_cst (itype));
2145 225 : t = fold_build2 (MULT_EXPR, itype, t, ostep);
2146 225 : t = fold_build2 (PLUS_EXPR, itype, n1o, t);
2147 225 : tree last = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
2148 : true, GSI_SAME_STMT);
2149 225 : tree n1, n2, n1e, n2e;
2150 225 : t = fold_convert (itype, unshare_expr (fd->loops[i].n1));
2151 225 : if (fd->loops[i].m1)
2152 : {
2153 205 : n1 = fold_convert (itype, unshare_expr (fd->loops[i].m1));
2154 205 : n1 = fold_build2 (MULT_EXPR, itype, n1o, n1);
2155 205 : n1 = fold_build2 (PLUS_EXPR, itype, n1, t);
2156 : }
2157 : else
2158 : n1 = t;
2159 225 : n1 = force_gimple_operand_gsi (&gsi2, n1, true, NULL_TREE,
2160 : true, GSI_SAME_STMT);
2161 225 : t = fold_convert (itype, unshare_expr (fd->loops[i].n2));
2162 225 : if (fd->loops[i].m2)
2163 : {
2164 63 : n2 = fold_convert (itype, unshare_expr (fd->loops[i].m2));
2165 63 : n2 = fold_build2 (MULT_EXPR, itype, n1o, n2);
2166 63 : n2 = fold_build2 (PLUS_EXPR, itype, n2, t);
2167 : }
2168 : else
2169 : n2 = t;
2170 225 : n2 = force_gimple_operand_gsi (&gsi2, n2, true, NULL_TREE,
2171 : true, GSI_SAME_STMT);
2172 225 : t = fold_convert (itype, unshare_expr (fd->loops[i].n1));
2173 225 : if (fd->loops[i].m1)
2174 : {
2175 205 : n1e = fold_convert (itype, unshare_expr (fd->loops[i].m1));
2176 205 : n1e = fold_build2 (MULT_EXPR, itype, last, n1e);
2177 205 : n1e = fold_build2 (PLUS_EXPR, itype, n1e, t);
2178 : }
2179 : else
2180 : n1e = t;
2181 225 : n1e = force_gimple_operand_gsi (&gsi2, n1e, true, NULL_TREE,
2182 : true, GSI_SAME_STMT);
2183 225 : t = fold_convert (itype, unshare_expr (fd->loops[i].n2));
2184 225 : if (fd->loops[i].m2)
2185 : {
2186 63 : n2e = fold_convert (itype, unshare_expr (fd->loops[i].m2));
2187 63 : n2e = fold_build2 (MULT_EXPR, itype, last, n2e);
2188 63 : n2e = fold_build2 (PLUS_EXPR, itype, n2e, t);
2189 : }
2190 : else
2191 : n2e = t;
2192 225 : n2e = force_gimple_operand_gsi (&gsi2, n2e, true, NULL_TREE,
2193 : true, GSI_SAME_STMT);
2194 225 : gcond *cond_stmt
2195 225 : = expand_omp_build_cond (&gsi2, fd->loops[i].cond_code,
2196 : n1, n2);
2197 225 : e = split_block (bb1, cond_stmt);
2198 225 : e->flags = EDGE_TRUE_VALUE;
2199 225 : e->probability = profile_probability::likely ().guessed ();
2200 225 : basic_block bb2 = e->dest;
2201 225 : gsi2 = gsi_after_labels (bb2);
2202 :
2203 225 : cond_stmt = expand_omp_build_cond (&gsi2, fd->loops[i].cond_code,
2204 : n1e, n2e);
2205 225 : e = split_block (bb2, cond_stmt);
2206 225 : e->flags = EDGE_TRUE_VALUE;
2207 225 : e->probability = profile_probability::likely ().guessed ();
2208 225 : gsi2 = gsi_after_labels (e->dest);
2209 :
2210 225 : tree step = fold_convert (itype, fd->loops[i].step);
2211 225 : t = build_int_cst (itype, (fd->loops[i].cond_code
2212 241 : == LT_EXPR ? -1 : 1));
2213 225 : t = fold_build2 (PLUS_EXPR, itype, step, t);
2214 225 : t = fold_build2 (PLUS_EXPR, itype, t, n2);
2215 225 : t = fold_build2 (MINUS_EXPR, itype, t, n1);
2216 225 : if (TYPE_UNSIGNED (itype)
2217 225 : && fd->loops[i].cond_code == GT_EXPR)
2218 0 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
2219 : fold_build1 (NEGATE_EXPR, itype, t),
2220 : fold_build1 (NEGATE_EXPR, itype, step));
2221 : else
2222 225 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
2223 225 : tree first_inner_iterations
2224 225 : = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
2225 : true, GSI_SAME_STMT);
2226 225 : t = fold_build2 (MULT_EXPR, itype, m2minusm1, ostep);
2227 225 : if (TYPE_UNSIGNED (itype)
2228 225 : && fd->loops[i].cond_code == GT_EXPR)
2229 0 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
2230 : fold_build1 (NEGATE_EXPR, itype, t),
2231 : fold_build1 (NEGATE_EXPR, itype, step));
2232 : else
2233 225 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
2234 225 : tree factor
2235 225 : = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
2236 : true, GSI_SAME_STMT);
2237 225 : t = fold_build2 (MINUS_EXPR, itype, outer_niters,
2238 : build_one_cst (itype));
2239 225 : t = fold_build2 (MULT_EXPR, itype, t, outer_niters);
2240 225 : t = fold_build2 (RSHIFT_EXPR, itype, t, integer_one_node);
2241 225 : t = fold_build2 (MULT_EXPR, itype, factor, t);
2242 225 : t = fold_build2 (PLUS_EXPR, itype,
2243 : fold_build2 (MULT_EXPR, itype, outer_niters,
2244 : first_inner_iterations), t);
2245 225 : expand_omp_build_assign (&gsi2, counts[fd->last_nonrect],
2246 : fold_convert (type, t));
2247 :
2248 225 : basic_block bb3 = create_empty_bb (bb1);
2249 225 : add_bb_to_loop (bb3, bb1->loop_father);
2250 :
2251 225 : e = make_edge (bb1, bb3, EDGE_FALSE_VALUE);
2252 225 : e->probability = profile_probability::unlikely ().guessed ();
2253 :
2254 225 : gsi2 = gsi_after_labels (bb3);
2255 225 : cond_stmt = expand_omp_build_cond (&gsi2, fd->loops[i].cond_code,
2256 : n1e, n2e);
2257 225 : e = split_block (bb3, cond_stmt);
2258 225 : e->flags = EDGE_TRUE_VALUE;
2259 225 : e->probability = profile_probability::likely ().guessed ();
2260 225 : basic_block bb4 = e->dest;
2261 :
2262 225 : ne = make_edge (bb3, entry_bb, EDGE_FALSE_VALUE);
2263 225 : ne->probability = e->probability.invert ();
2264 :
2265 225 : basic_block bb5 = create_empty_bb (bb2);
2266 225 : add_bb_to_loop (bb5, bb2->loop_father);
2267 :
2268 225 : ne = make_edge (bb2, bb5, EDGE_FALSE_VALUE);
2269 225 : ne->probability = profile_probability::unlikely ().guessed ();
2270 :
2271 675 : for (int j = 0; j < 2; j++)
2272 : {
2273 450 : gsi2 = gsi_after_labels (j ? bb5 : bb4);
2274 450 : t = fold_build2 (MINUS_EXPR, itype,
2275 : unshare_expr (fd->loops[i].n1),
2276 : unshare_expr (fd->loops[i].n2));
2277 450 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, m2minusm1);
2278 450 : tree tem
2279 450 : = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
2280 : true, GSI_SAME_STMT);
2281 450 : t = fold_build2 (MINUS_EXPR, itype, tem, n1o);
2282 450 : t = fold_build2 (TRUNC_MOD_EXPR, itype, t, ostep);
2283 450 : t = fold_build2 (MINUS_EXPR, itype, tem, t);
2284 450 : tem = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
2285 : true, GSI_SAME_STMT);
2286 450 : t = fold_convert (itype, unshare_expr (fd->loops[i].n1));
2287 450 : if (fd->loops[i].m1)
2288 : {
2289 410 : n1 = fold_convert (itype, unshare_expr (fd->loops[i].m1));
2290 410 : n1 = fold_build2 (MULT_EXPR, itype, tem, n1);
2291 410 : n1 = fold_build2 (PLUS_EXPR, itype, n1, t);
2292 : }
2293 : else
2294 : n1 = t;
2295 450 : n1 = force_gimple_operand_gsi (&gsi2, n1, true, NULL_TREE,
2296 : true, GSI_SAME_STMT);
2297 450 : t = fold_convert (itype, unshare_expr (fd->loops[i].n2));
2298 450 : if (fd->loops[i].m2)
2299 : {
2300 126 : n2 = fold_convert (itype, unshare_expr (fd->loops[i].m2));
2301 126 : n2 = fold_build2 (MULT_EXPR, itype, tem, n2);
2302 126 : n2 = fold_build2 (PLUS_EXPR, itype, n2, t);
2303 : }
2304 : else
2305 : n2 = t;
2306 450 : n2 = force_gimple_operand_gsi (&gsi2, n2, true, NULL_TREE,
2307 : true, GSI_SAME_STMT);
2308 675 : expand_omp_build_assign (&gsi2, j ? n2o : n1o, tem);
2309 :
2310 450 : cond_stmt = expand_omp_build_cond (&gsi2, fd->loops[i].cond_code,
2311 : n1, n2);
2312 450 : e = split_block (gsi_bb (gsi2), cond_stmt);
2313 450 : e->flags = j ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE;
2314 450 : e->probability = profile_probability::unlikely ().guessed ();
2315 675 : ne = make_edge (e->src, bb1,
2316 : j ? EDGE_FALSE_VALUE : EDGE_TRUE_VALUE);
2317 450 : ne->probability = e->probability.invert ();
2318 450 : gsi2 = gsi_after_labels (e->dest);
2319 :
2320 450 : t = fold_build2 (PLUS_EXPR, itype, tem, ostep);
2321 450 : expand_omp_build_assign (&gsi2, j ? n2o : n1o, t);
2322 :
2323 450 : make_edge (e->dest, bb1, EDGE_FALLTHRU);
2324 : }
2325 :
2326 225 : set_immediate_dominator (CDI_DOMINATORS, bb3, bb1);
2327 225 : set_immediate_dominator (CDI_DOMINATORS, bb5, bb2);
2328 225 : set_immediate_dominator (CDI_DOMINATORS, entry_bb, bb1);
2329 :
2330 225 : if (fd->first_nonrect + 1 == fd->last_nonrect)
2331 : {
2332 153 : fd->first_inner_iterations = first_inner_iterations;
2333 153 : fd->factor = factor;
2334 153 : fd->adjn1 = n1o;
2335 : }
2336 : }
2337 : else
2338 : {
2339 : /* Fallback implementation. Evaluate the loops with m1/m2
2340 : non-NULL as well as their outer loops at runtime using temporaries
2341 : instead of the original iteration variables, and in the
2342 : body just bump the counter. */
2343 59 : gimple_stmt_iterator gsi2 = *gsi;
2344 59 : gsi_prev (&gsi2);
2345 59 : e = split_block (entry_bb, gsi_stmt (gsi2));
2346 59 : e = split_block (e->dest, (gimple *) NULL);
2347 59 : basic_block cur_bb = e->src;
2348 59 : basic_block next_bb = e->dest;
2349 59 : entry_bb = e->dest;
2350 59 : *gsi = gsi_after_labels (entry_bb);
2351 :
2352 59 : tree *vs = XALLOCAVEC (tree, fd->last_nonrect);
2353 59 : memset (vs, 0, fd->last_nonrect * sizeof (tree));
2354 :
2355 189 : for (i = 0; i <= fd->last_nonrect; i++)
2356 : {
2357 189 : if (fd->loops[i].m1 == NULL_TREE
2358 108 : && fd->loops[i].m2 == NULL_TREE
2359 99 : && !fd->loops[i].non_rect_referenced)
2360 40 : continue;
2361 :
2362 149 : tree itype = TREE_TYPE (fd->loops[i].v);
2363 :
2364 149 : gsi2 = gsi_after_labels (cur_bb);
2365 149 : tree n1, n2;
2366 149 : t = fold_convert (itype, unshare_expr (fd->loops[i].n1));
2367 149 : if (fd->loops[i].m1 == NULL_TREE)
2368 : n1 = t;
2369 81 : else if (POINTER_TYPE_P (itype))
2370 : {
2371 30 : gcc_assert (integer_onep (fd->loops[i].m1));
2372 30 : t = unshare_expr (fd->loops[i].n1);
2373 30 : n1 = fold_build_pointer_plus (vs[i - fd->loops[i].outer], t);
2374 : }
2375 : else
2376 : {
2377 51 : n1 = fold_convert (itype, unshare_expr (fd->loops[i].m1));
2378 51 : n1 = fold_build2 (MULT_EXPR, itype,
2379 : vs[i - fd->loops[i].outer], n1);
2380 51 : n1 = fold_build2 (PLUS_EXPR, itype, n1, t);
2381 : }
2382 149 : n1 = force_gimple_operand_gsi (&gsi2, n1, true, NULL_TREE,
2383 : true, GSI_SAME_STMT);
2384 149 : if (i < fd->last_nonrect)
2385 : {
2386 90 : vs[i] = create_tmp_reg (itype, ".it");
2387 90 : expand_omp_build_assign (&gsi2, vs[i], n1);
2388 : }
2389 149 : t = fold_convert (itype, unshare_expr (fd->loops[i].n2));
2390 149 : if (fd->loops[i].m2 == NULL_TREE)
2391 : n2 = t;
2392 85 : else if (POINTER_TYPE_P (itype))
2393 : {
2394 34 : gcc_assert (integer_onep (fd->loops[i].m2));
2395 34 : t = unshare_expr (fd->loops[i].n2);
2396 34 : n2 = fold_build_pointer_plus (vs[i - fd->loops[i].outer], t);
2397 : }
2398 : else
2399 : {
2400 51 : n2 = fold_convert (itype, unshare_expr (fd->loops[i].m2));
2401 51 : n2 = fold_build2 (MULT_EXPR, itype,
2402 : vs[i - fd->loops[i].outer], n2);
2403 51 : n2 = fold_build2 (PLUS_EXPR, itype, n2, t);
2404 : }
2405 149 : n2 = force_gimple_operand_gsi (&gsi2, n2, true, NULL_TREE,
2406 : true, GSI_SAME_STMT);
2407 149 : if (POINTER_TYPE_P (itype))
2408 70 : itype = signed_type_for (itype);
2409 149 : if (i == fd->last_nonrect)
2410 : {
2411 59 : gcond *cond_stmt
2412 59 : = expand_omp_build_cond (&gsi2, fd->loops[i].cond_code,
2413 : n1, n2);
2414 59 : e = split_block (cur_bb, cond_stmt);
2415 59 : e->flags = EDGE_TRUE_VALUE;
2416 59 : ne = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
2417 59 : e->probability = profile_probability::likely ().guessed ();
2418 59 : ne->probability = e->probability.invert ();
2419 59 : gsi2 = gsi_after_labels (e->dest);
2420 :
2421 59 : t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
2422 79 : ? -1 : 1));
2423 59 : t = fold_build2 (PLUS_EXPR, itype,
2424 : fold_convert (itype, fd->loops[i].step), t);
2425 59 : t = fold_build2 (PLUS_EXPR, itype, t,
2426 : fold_convert (itype, n2));
2427 59 : t = fold_build2 (MINUS_EXPR, itype, t,
2428 : fold_convert (itype, n1));
2429 59 : tree step = fold_convert (itype, fd->loops[i].step);
2430 59 : if (TYPE_UNSIGNED (itype)
2431 59 : && fd->loops[i].cond_code == GT_EXPR)
2432 0 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
2433 : fold_build1 (NEGATE_EXPR, itype, t),
2434 : fold_build1 (NEGATE_EXPR, itype, step));
2435 : else
2436 59 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
2437 59 : t = fold_convert (type, t);
2438 59 : t = fold_build2 (PLUS_EXPR, type,
2439 : counts[fd->last_nonrect], t);
2440 59 : t = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
2441 : true, GSI_SAME_STMT);
2442 59 : expand_omp_build_assign (&gsi2, counts[fd->last_nonrect], t);
2443 59 : e = make_edge (e->dest, next_bb, EDGE_FALLTHRU);
2444 59 : set_immediate_dominator (CDI_DOMINATORS, next_bb, cur_bb);
2445 59 : break;
2446 : }
2447 90 : e = split_block (cur_bb, last_nondebug_stmt (cur_bb));
2448 :
2449 90 : basic_block new_cur_bb = create_empty_bb (cur_bb);
2450 90 : add_bb_to_loop (new_cur_bb, cur_bb->loop_father);
2451 :
2452 90 : gsi2 = gsi_after_labels (e->dest);
2453 90 : tree step = fold_convert (itype,
2454 : unshare_expr (fd->loops[i].step));
2455 90 : if (POINTER_TYPE_P (TREE_TYPE (vs[i])))
2456 38 : t = fold_build_pointer_plus (vs[i], step);
2457 : else
2458 52 : t = fold_build2 (PLUS_EXPR, itype, vs[i], step);
2459 90 : t = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
2460 : true, GSI_SAME_STMT);
2461 90 : expand_omp_build_assign (&gsi2, vs[i], t);
2462 :
2463 90 : ne = split_block (e->dest, last_nondebug_stmt (e->dest));
2464 90 : gsi2 = gsi_after_labels (ne->dest);
2465 :
2466 90 : expand_omp_build_cond (&gsi2, fd->loops[i].cond_code, vs[i], n2);
2467 90 : edge e3, e4;
2468 90 : if (next_bb == entry_bb)
2469 : {
2470 59 : e3 = find_edge (ne->dest, next_bb);
2471 59 : e3->flags = EDGE_FALSE_VALUE;
2472 : }
2473 : else
2474 31 : e3 = make_edge (ne->dest, next_bb, EDGE_FALSE_VALUE);
2475 90 : e4 = make_edge (ne->dest, new_cur_bb, EDGE_TRUE_VALUE);
2476 90 : e4->probability = profile_probability::likely ().guessed ();
2477 90 : e3->probability = e4->probability.invert ();
2478 90 : basic_block esrc = e->src;
2479 90 : make_edge (e->src, ne->dest, EDGE_FALLTHRU);
2480 90 : cur_bb = new_cur_bb;
2481 90 : basic_block latch_bb = next_bb;
2482 90 : next_bb = e->dest;
2483 90 : remove_edge (e);
2484 90 : set_immediate_dominator (CDI_DOMINATORS, ne->dest, esrc);
2485 90 : set_immediate_dominator (CDI_DOMINATORS, latch_bb, ne->dest);
2486 90 : set_immediate_dominator (CDI_DOMINATORS, cur_bb, ne->dest);
2487 : }
2488 : }
2489 284 : t = NULL_TREE;
2490 691 : for (i = fd->first_nonrect; i < fd->last_nonrect; i++)
2491 407 : if (!fd->loops[i].non_rect_referenced
2492 92 : && fd->loops[i].m1 == NULL_TREE
2493 92 : && fd->loops[i].m2 == NULL_TREE)
2494 : {
2495 92 : if (t == NULL_TREE)
2496 82 : t = counts[i];
2497 : else
2498 10 : t = fold_build2 (MULT_EXPR, type, t, counts[i]);
2499 : }
2500 284 : if (t)
2501 : {
2502 82 : t = fold_build2 (MULT_EXPR, type, counts[fd->last_nonrect], t);
2503 82 : expand_omp_build_assign (gsi, counts[fd->last_nonrect], t);
2504 : }
2505 284 : if (!rect_count_seen)
2506 186 : t = counts[fd->last_nonrect];
2507 : else
2508 98 : t = fold_build2 (MULT_EXPR, type, fd->loop.n2,
2509 : counts[fd->last_nonrect]);
2510 284 : expand_omp_build_assign (gsi, fd->loop.n2, t);
2511 284 : }
2512 7485 : else if (fd->non_rect)
2513 : {
2514 117 : tree t = fd->loop.n2;
2515 117 : gcc_assert (TREE_CODE (t) == INTEGER_CST);
2516 : int non_rect_referenced = 0, non_rect = 0;
2517 358 : for (i = 0; i < fd->collapse; i++)
2518 : {
2519 240 : if ((i < fd->first_nonrect || i > fd->last_nonrect)
2520 246 : && !integer_zerop (counts[i]))
2521 6 : t = fold_build2 (TRUNC_DIV_EXPR, type, t, counts[i]);
2522 241 : if (fd->loops[i].non_rect_referenced)
2523 117 : non_rect_referenced++;
2524 241 : if (fd->loops[i].m1 || fd->loops[i].m2)
2525 117 : non_rect++;
2526 : }
2527 117 : gcc_assert (non_rect == 1 && non_rect_referenced == 1);
2528 117 : counts[fd->last_nonrect] = t;
2529 : }
2530 : }
2531 :
2532 : /* Helper function for expand_omp_{for_*,simd}. Generate code like:
2533 : T = V;
2534 : V3 = N31 + (T % count3) * STEP3;
2535 : T = T / count3;
2536 : V2 = N21 + (T % count2) * STEP2;
2537 : T = T / count2;
2538 : V1 = N11 + T * STEP1;
2539 : if this loop doesn't have an inner loop construct combined with it.
2540 : If it does have an inner loop construct combined with it and the
2541 : iteration count isn't known constant, store values from counts array
2542 : into its _looptemp_ temporaries instead.
2543 : For non-rectangular loops (between fd->first_nonrect and fd->last_nonrect
2544 : inclusive), use the count of all those loops together, and either
2545 : find quadratic etc. equation roots, or as a fallback, do:
2546 : COUNT = 0;
2547 : for (tmpi = N11; tmpi COND1 N12; tmpi += STEP1)
2548 : for (tmpj = M21 * tmpi + N21;
2549 : tmpj COND2 M22 * tmpi + N22; tmpj += STEP2)
2550 : {
2551 : int tmpk1 = M31 * tmpj + N31;
2552 : int tmpk2 = M32 * tmpj + N32;
2553 : if (tmpk1 COND3 tmpk2)
2554 : {
2555 : if (COND3 is <)
2556 : adj = STEP3 - 1;
2557 : else
2558 : adj = STEP3 + 1;
2559 : int temp = (adj + tmpk2 - tmpk1) / STEP3;
2560 : if (COUNT + temp > T)
2561 : {
2562 : V1 = tmpi;
2563 : V2 = tmpj;
2564 : V3 = tmpk1 + (T - COUNT) * STEP3;
2565 : goto done;
2566 : }
2567 : else
2568 : COUNT += temp;
2569 : }
2570 : }
2571 : done:;
2572 : but for optional innermost or outermost rectangular loops that aren't
2573 : referenced by other loop expressions keep doing the division/modulo. */
2574 :
2575 : static void
2576 10273 : expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
2577 : tree *counts, tree *nonrect_bounds,
2578 : gimple *inner_stmt, tree startvar)
2579 : {
2580 10273 : int i;
2581 10273 : if (gimple_omp_for_combined_p (fd->for_stmt))
2582 : {
2583 : /* If fd->loop.n2 is constant, then no propagation of the counts
2584 : is needed, they are constant. */
2585 4867 : if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
2586 : return;
2587 :
2588 2692 : tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
2589 4158 : ? gimple_omp_taskreg_clauses (inner_stmt)
2590 1226 : : gimple_omp_for_clauses (inner_stmt);
2591 : /* First two _looptemp_ clauses are for istart/iend, counts[0]
2592 : isn't supposed to be handled, as the inner loop doesn't
2593 : use it. */
2594 2692 : tree innerc = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
2595 2692 : gcc_assert (innerc);
2596 2692 : int count = 0;
2597 2692 : if (fd->non_rect
2598 112 : && fd->last_nonrect == fd->first_nonrect + 1
2599 2756 : && !TYPE_UNSIGNED (TREE_TYPE (fd->loops[fd->last_nonrect].v)))
2600 : count = 4;
2601 10793 : for (i = 0; i < fd->collapse + count; i++)
2602 : {
2603 8101 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
2604 : OMP_CLAUSE__LOOPTEMP_);
2605 8101 : gcc_assert (innerc);
2606 8101 : if (i)
2607 : {
2608 5409 : tree tem = OMP_CLAUSE_DECL (innerc);
2609 5409 : tree t;
2610 5409 : if (i < fd->collapse)
2611 5169 : t = counts[i];
2612 : else
2613 240 : switch (i - fd->collapse)
2614 : {
2615 60 : case 0: t = counts[0]; break;
2616 60 : case 1: t = fd->first_inner_iterations; break;
2617 60 : case 2: t = fd->factor; break;
2618 60 : case 3: t = fd->adjn1; break;
2619 0 : default: gcc_unreachable ();
2620 : }
2621 5409 : t = fold_convert (TREE_TYPE (tem), t);
2622 5409 : t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
2623 : false, GSI_CONTINUE_LINKING);
2624 5409 : gassign *stmt = gimple_build_assign (tem, t);
2625 5409 : gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
2626 : }
2627 : }
2628 : return;
2629 : }
2630 :
2631 5406 : tree type = TREE_TYPE (fd->loop.v);
2632 5406 : tree tem = create_tmp_reg (type, ".tem");
2633 5406 : gassign *stmt = gimple_build_assign (tem, startvar);
2634 5406 : gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
2635 :
2636 20106 : for (i = fd->collapse - 1; i >= 0; i--)
2637 : {
2638 14700 : tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
2639 14700 : itype = vtype;
2640 14700 : if (POINTER_TYPE_P (vtype))
2641 1649 : itype = signed_type_for (vtype);
2642 14700 : if (i != 0 && (i != fd->last_nonrect || fd->first_nonrect))
2643 9294 : t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
2644 : else
2645 : t = tem;
2646 14700 : if (i == fd->last_nonrect)
2647 : {
2648 376 : t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
2649 : false, GSI_CONTINUE_LINKING);
2650 376 : tree stopval = t;
2651 376 : tree idx = create_tmp_reg (type, ".count");
2652 376 : expand_omp_build_assign (gsi, idx,
2653 : build_zero_cst (type), true);
2654 376 : basic_block bb_triang = NULL, bb_triang_dom = NULL;
2655 376 : if (fd->first_nonrect + 1 == fd->last_nonrect
2656 272 : && (TREE_CODE (fd->loop.n2) == INTEGER_CST
2657 181 : || fd->first_inner_iterations)
2658 488 : && (optab_handler (sqrt_optab, TYPE_MODE (double_type_node))
2659 : != CODE_FOR_nothing)
2660 620 : && !integer_zerop (fd->loop.n2))
2661 : {
2662 236 : tree outer_n1 = fd->adjn1 ? fd->adjn1 : fd->loops[i - 1].n1;
2663 236 : tree itype = TREE_TYPE (fd->loops[i].v);
2664 236 : tree first_inner_iterations = fd->first_inner_iterations;
2665 236 : tree factor = fd->factor;
2666 236 : gcond *cond_stmt
2667 236 : = expand_omp_build_cond (gsi, NE_EXPR, factor,
2668 236 : build_zero_cst (TREE_TYPE (factor)),
2669 : true);
2670 236 : edge e = split_block (gsi_bb (*gsi), cond_stmt);
2671 236 : basic_block bb0 = e->src;
2672 236 : e->flags = EDGE_TRUE_VALUE;
2673 236 : e->probability = profile_probability::likely ();
2674 236 : bb_triang_dom = bb0;
2675 236 : *gsi = gsi_after_labels (e->dest);
2676 236 : tree slltype = long_long_integer_type_node;
2677 236 : tree ulltype = long_long_unsigned_type_node;
2678 236 : tree stopvalull = fold_convert (ulltype, stopval);
2679 236 : stopvalull
2680 236 : = force_gimple_operand_gsi (gsi, stopvalull, true, NULL_TREE,
2681 : false, GSI_CONTINUE_LINKING);
2682 236 : first_inner_iterations
2683 236 : = fold_convert (slltype, first_inner_iterations);
2684 236 : first_inner_iterations
2685 236 : = force_gimple_operand_gsi (gsi, first_inner_iterations, true,
2686 : NULL_TREE, false,
2687 : GSI_CONTINUE_LINKING);
2688 236 : factor = fold_convert (slltype, factor);
2689 236 : factor
2690 236 : = force_gimple_operand_gsi (gsi, factor, true, NULL_TREE,
2691 : false, GSI_CONTINUE_LINKING);
2692 236 : tree first_inner_iterationsd
2693 236 : = fold_build1 (FLOAT_EXPR, double_type_node,
2694 : first_inner_iterations);
2695 236 : first_inner_iterationsd
2696 236 : = force_gimple_operand_gsi (gsi, first_inner_iterationsd, true,
2697 : NULL_TREE, false,
2698 : GSI_CONTINUE_LINKING);
2699 236 : tree factord = fold_build1 (FLOAT_EXPR, double_type_node,
2700 : factor);
2701 236 : factord = force_gimple_operand_gsi (gsi, factord, true,
2702 : NULL_TREE, false,
2703 : GSI_CONTINUE_LINKING);
2704 236 : tree stopvald = fold_build1 (FLOAT_EXPR, double_type_node,
2705 : stopvalull);
2706 236 : stopvald = force_gimple_operand_gsi (gsi, stopvald, true,
2707 : NULL_TREE, false,
2708 : GSI_CONTINUE_LINKING);
2709 : /* Temporarily disable flag_rounding_math, values will be
2710 : decimal numbers divided by 2 and worst case imprecisions
2711 : due to too large values ought to be caught later by the
2712 : checks for fallback. */
2713 236 : int save_flag_rounding_math = flag_rounding_math;
2714 236 : flag_rounding_math = 0;
2715 236 : t = fold_build2 (RDIV_EXPR, double_type_node, factord,
2716 : build_real (double_type_node, dconst2));
2717 236 : tree t3 = fold_build2 (MINUS_EXPR, double_type_node,
2718 : first_inner_iterationsd, t);
2719 236 : t3 = force_gimple_operand_gsi (gsi, t3, true, NULL_TREE, false,
2720 : GSI_CONTINUE_LINKING);
2721 236 : t = fold_build2 (MULT_EXPR, double_type_node, factord,
2722 : build_real (double_type_node, dconst2));
2723 236 : t = fold_build2 (MULT_EXPR, double_type_node, t, stopvald);
2724 236 : t = fold_build2 (PLUS_EXPR, double_type_node, t,
2725 : fold_build2 (MULT_EXPR, double_type_node,
2726 : t3, t3));
2727 236 : flag_rounding_math = save_flag_rounding_math;
2728 236 : t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, false,
2729 : GSI_CONTINUE_LINKING);
2730 236 : if (flag_exceptions
2731 34 : && cfun->can_throw_non_call_exceptions
2732 244 : && operation_could_trap_p (LT_EXPR, true, false, NULL_TREE))
2733 : {
2734 8 : tree tem = fold_build2 (LT_EXPR, boolean_type_node, t,
2735 : build_zero_cst (double_type_node));
2736 8 : tem = force_gimple_operand_gsi (gsi, tem, true, NULL_TREE,
2737 : false, GSI_CONTINUE_LINKING);
2738 8 : cond_stmt = gimple_build_cond (NE_EXPR, tem,
2739 : boolean_false_node,
2740 : NULL_TREE, NULL_TREE);
2741 : }
2742 : else
2743 228 : cond_stmt
2744 228 : = gimple_build_cond (LT_EXPR, t,
2745 : build_zero_cst (double_type_node),
2746 : NULL_TREE, NULL_TREE);
2747 236 : gsi_insert_after (gsi, cond_stmt, GSI_CONTINUE_LINKING);
2748 236 : e = split_block (gsi_bb (*gsi), cond_stmt);
2749 236 : basic_block bb1 = e->src;
2750 236 : e->flags = EDGE_FALSE_VALUE;
2751 236 : e->probability = profile_probability::very_likely ();
2752 236 : *gsi = gsi_after_labels (e->dest);
2753 236 : gcall *call = gimple_build_call_internal (IFN_SQRT, 1, t);
2754 236 : tree sqrtr = create_tmp_var (double_type_node);
2755 236 : gimple_call_set_lhs (call, sqrtr);
2756 236 : gsi_insert_after (gsi, call, GSI_CONTINUE_LINKING);
2757 236 : t = fold_build2 (MINUS_EXPR, double_type_node, sqrtr, t3);
2758 236 : t = fold_build2 (RDIV_EXPR, double_type_node, t, factord);
2759 236 : t = fold_build1 (FIX_TRUNC_EXPR, ulltype, t);
2760 236 : tree c = create_tmp_var (ulltype);
2761 236 : tree d = create_tmp_var (ulltype);
2762 236 : expand_omp_build_assign (gsi, c, t, true);
2763 236 : t = fold_build2 (MINUS_EXPR, ulltype, c,
2764 : build_one_cst (ulltype));
2765 236 : t = fold_build2 (MULT_EXPR, ulltype, c, t);
2766 236 : t = fold_build2 (RSHIFT_EXPR, ulltype, t, integer_one_node);
2767 236 : t = fold_build2 (MULT_EXPR, ulltype,
2768 : fold_convert (ulltype, fd->factor), t);
2769 236 : tree t2
2770 236 : = fold_build2 (MULT_EXPR, ulltype, c,
2771 : fold_convert (ulltype,
2772 : fd->first_inner_iterations));
2773 236 : t = fold_build2 (PLUS_EXPR, ulltype, t, t2);
2774 236 : expand_omp_build_assign (gsi, d, t, true);
2775 236 : t = fold_build2 (MULT_EXPR, ulltype,
2776 : fold_convert (ulltype, fd->factor), c);
2777 236 : t = fold_build2 (PLUS_EXPR, ulltype,
2778 : t, fold_convert (ulltype,
2779 : fd->first_inner_iterations));
2780 236 : t2 = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, false,
2781 : GSI_CONTINUE_LINKING);
2782 236 : cond_stmt = gimple_build_cond (GE_EXPR, stopvalull, d,
2783 : NULL_TREE, NULL_TREE);
2784 236 : gsi_insert_after (gsi, cond_stmt, GSI_CONTINUE_LINKING);
2785 236 : e = split_block (gsi_bb (*gsi), cond_stmt);
2786 236 : basic_block bb2 = e->src;
2787 236 : e->flags = EDGE_TRUE_VALUE;
2788 236 : e->probability = profile_probability::very_likely ();
2789 236 : *gsi = gsi_after_labels (e->dest);
2790 236 : t = fold_build2 (PLUS_EXPR, ulltype, d, t2);
2791 236 : t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, false,
2792 : GSI_CONTINUE_LINKING);
2793 236 : cond_stmt = gimple_build_cond (GE_EXPR, stopvalull, t,
2794 : NULL_TREE, NULL_TREE);
2795 236 : gsi_insert_after (gsi, cond_stmt, GSI_CONTINUE_LINKING);
2796 236 : e = split_block (gsi_bb (*gsi), cond_stmt);
2797 236 : basic_block bb3 = e->src;
2798 236 : e->flags = EDGE_FALSE_VALUE;
2799 236 : e->probability = profile_probability::very_likely ();
2800 236 : *gsi = gsi_after_labels (e->dest);
2801 236 : t = fold_convert (itype, c);
2802 236 : t = fold_build2 (MULT_EXPR, itype, t, fd->loops[i - 1].step);
2803 236 : t = fold_build2 (PLUS_EXPR, itype, outer_n1, t);
2804 236 : t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, false,
2805 : GSI_CONTINUE_LINKING);
2806 236 : expand_omp_build_assign (gsi, fd->loops[i - 1].v, t, true);
2807 236 : t2 = fold_build2 (MINUS_EXPR, ulltype, stopvalull, d);
2808 236 : t2 = fold_convert (itype, t2);
2809 236 : t2 = fold_build2 (MULT_EXPR, itype, t2, fd->loops[i].step);
2810 236 : t2 = fold_build2 (PLUS_EXPR, itype, t2, fd->loops[i].n1);
2811 236 : if (fd->loops[i].m1)
2812 : {
2813 195 : t = fold_build2 (MULT_EXPR, itype, t, fd->loops[i].m1);
2814 195 : t2 = fold_build2 (PLUS_EXPR, itype, t2, t);
2815 : }
2816 236 : expand_omp_build_assign (gsi, fd->loops[i].v, t2, true);
2817 236 : e = split_block (gsi_bb (*gsi), gsi_stmt (*gsi));
2818 236 : bb_triang = e->src;
2819 236 : *gsi = gsi_after_labels (e->dest);
2820 236 : remove_edge (e);
2821 236 : e = make_edge (bb1, gsi_bb (*gsi), EDGE_TRUE_VALUE);
2822 236 : e->probability = profile_probability::very_unlikely ();
2823 236 : e = make_edge (bb2, gsi_bb (*gsi), EDGE_FALSE_VALUE);
2824 236 : e->probability = profile_probability::very_unlikely ();
2825 236 : e = make_edge (bb3, gsi_bb (*gsi), EDGE_TRUE_VALUE);
2826 236 : e->probability = profile_probability::very_unlikely ();
2827 :
2828 236 : basic_block bb4 = create_empty_bb (bb0);
2829 236 : add_bb_to_loop (bb4, bb0->loop_father);
2830 236 : e = make_edge (bb0, bb4, EDGE_FALSE_VALUE);
2831 236 : e->probability = profile_probability::unlikely ();
2832 236 : make_edge (bb4, gsi_bb (*gsi), EDGE_FALLTHRU);
2833 236 : set_immediate_dominator (CDI_DOMINATORS, bb4, bb0);
2834 236 : set_immediate_dominator (CDI_DOMINATORS, gsi_bb (*gsi), bb0);
2835 236 : gimple_stmt_iterator gsi2 = gsi_after_labels (bb4);
2836 236 : t2 = fold_build2 (TRUNC_DIV_EXPR, type,
2837 : counts[i], counts[i - 1]);
2838 236 : t2 = force_gimple_operand_gsi (&gsi2, t2, true, NULL_TREE, false,
2839 : GSI_CONTINUE_LINKING);
2840 236 : t = fold_build2 (TRUNC_MOD_EXPR, type, stopval, t2);
2841 236 : t2 = fold_build2 (TRUNC_DIV_EXPR, type, stopval, t2);
2842 236 : t = fold_convert (itype, t);
2843 236 : t2 = fold_convert (itype, t2);
2844 236 : t = fold_build2 (MULT_EXPR, itype, t,
2845 : fold_convert (itype, fd->loops[i].step));
2846 236 : t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
2847 236 : t2 = fold_build2 (MULT_EXPR, itype, t2,
2848 : fold_convert (itype, fd->loops[i - 1].step));
2849 236 : t2 = fold_build2 (PLUS_EXPR, itype, fd->loops[i - 1].n1, t2);
2850 236 : t2 = force_gimple_operand_gsi (&gsi2, t2, false, NULL_TREE,
2851 : false, GSI_CONTINUE_LINKING);
2852 236 : stmt = gimple_build_assign (fd->loops[i - 1].v, t2);
2853 236 : gsi_insert_after (&gsi2, stmt, GSI_CONTINUE_LINKING);
2854 236 : if (fd->loops[i].m1)
2855 : {
2856 195 : t2 = fold_build2 (MULT_EXPR, itype, fd->loops[i].m1,
2857 : fd->loops[i - 1].v);
2858 195 : t = fold_build2 (PLUS_EXPR, itype, t, t2);
2859 : }
2860 236 : t = force_gimple_operand_gsi (&gsi2, t, false, NULL_TREE,
2861 : false, GSI_CONTINUE_LINKING);
2862 236 : stmt = gimple_build_assign (fd->loops[i].v, t);
2863 236 : gsi_insert_after (&gsi2, stmt, GSI_CONTINUE_LINKING);
2864 : }
2865 : /* Fallback implementation. Evaluate the loops in between
2866 : (inclusive) fd->first_nonrect and fd->last_nonrect at
2867 : runtime using temporaries instead of the original iteration
2868 : variables, in the body just bump the counter and compare
2869 : with the desired value. */
2870 376 : gimple_stmt_iterator gsi2 = *gsi;
2871 376 : basic_block entry_bb = gsi_bb (gsi2);
2872 376 : edge e = split_block (entry_bb, gsi_stmt (gsi2));
2873 376 : e = split_block (e->dest, (gimple *) NULL);
2874 376 : basic_block dom_bb = NULL;
2875 376 : basic_block cur_bb = e->src;
2876 376 : basic_block next_bb = e->dest;
2877 376 : entry_bb = e->dest;
2878 376 : *gsi = gsi_after_labels (entry_bb);
2879 :
2880 376 : tree *vs = XALLOCAVEC (tree, fd->last_nonrect);
2881 376 : tree n1 = NULL_TREE, n2 = NULL_TREE;
2882 376 : memset (vs, 0, fd->last_nonrect * sizeof (tree));
2883 :
2884 876 : for (int j = fd->first_nonrect; j <= fd->last_nonrect; j++)
2885 : {
2886 876 : tree itype = TREE_TYPE (fd->loops[j].v);
2887 1752 : bool rect_p = (fd->loops[j].m1 == NULL_TREE
2888 527 : && fd->loops[j].m2 == NULL_TREE
2889 1345 : && !fd->loops[j].non_rect_referenced);
2890 876 : gsi2 = gsi_after_labels (cur_bb);
2891 876 : t = fold_convert (itype, unshare_expr (fd->loops[j].n1));
2892 876 : if (fd->loops[j].m1 == NULL_TREE)
2893 527 : n1 = rect_p ? build_zero_cst (type) : t;
2894 349 : else if (POINTER_TYPE_P (itype))
2895 : {
2896 30 : gcc_assert (integer_onep (fd->loops[j].m1));
2897 30 : t = unshare_expr (fd->loops[j].n1);
2898 30 : n1 = fold_build_pointer_plus (vs[j - fd->loops[j].outer], t);
2899 : }
2900 : else
2901 : {
2902 319 : n1 = fold_convert (itype, unshare_expr (fd->loops[j].m1));
2903 319 : n1 = fold_build2 (MULT_EXPR, itype,
2904 : vs[j - fd->loops[j].outer], n1);
2905 319 : n1 = fold_build2 (PLUS_EXPR, itype, n1, t);
2906 : }
2907 876 : n1 = force_gimple_operand_gsi (&gsi2, n1, true, NULL_TREE,
2908 : true, GSI_SAME_STMT);
2909 876 : if (j < fd->last_nonrect)
2910 : {
2911 907 : vs[j] = create_tmp_reg (rect_p ? type : itype, ".it");
2912 500 : expand_omp_build_assign (&gsi2, vs[j], n1);
2913 : }
2914 876 : t = fold_convert (itype, unshare_expr (fd->loops[j].n2));
2915 876 : if (fd->loops[j].m2 == NULL_TREE)
2916 646 : n2 = rect_p ? counts[j] : t;
2917 230 : else if (POINTER_TYPE_P (itype))
2918 : {
2919 34 : gcc_assert (integer_onep (fd->loops[j].m2));
2920 34 : t = unshare_expr (fd->loops[j].n2);
2921 34 : n2 = fold_build_pointer_plus (vs[j - fd->loops[j].outer], t);
2922 : }
2923 : else
2924 : {
2925 196 : n2 = fold_convert (itype, unshare_expr (fd->loops[j].m2));
2926 196 : n2 = fold_build2 (MULT_EXPR, itype,
2927 : vs[j - fd->loops[j].outer], n2);
2928 196 : n2 = fold_build2 (PLUS_EXPR, itype, n2, t);
2929 : }
2930 876 : n2 = force_gimple_operand_gsi (&gsi2, n2, true, NULL_TREE,
2931 : true, GSI_SAME_STMT);
2932 876 : if (POINTER_TYPE_P (itype))
2933 74 : itype = signed_type_for (itype);
2934 876 : if (j == fd->last_nonrect)
2935 : {
2936 376 : gcond *cond_stmt
2937 376 : = expand_omp_build_cond (&gsi2, fd->loops[i].cond_code,
2938 : n1, n2);
2939 376 : e = split_block (cur_bb, cond_stmt);
2940 376 : e->flags = EDGE_TRUE_VALUE;
2941 376 : edge ne = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
2942 376 : e->probability = profile_probability::likely ().guessed ();
2943 376 : ne->probability = e->probability.invert ();
2944 376 : gsi2 = gsi_after_labels (e->dest);
2945 :
2946 376 : t = build_int_cst (itype, (fd->loops[j].cond_code == LT_EXPR
2947 428 : ? -1 : 1));
2948 376 : t = fold_build2 (PLUS_EXPR, itype,
2949 : fold_convert (itype, fd->loops[j].step), t);
2950 376 : t = fold_build2 (PLUS_EXPR, itype, t,
2951 : fold_convert (itype, n2));
2952 376 : t = fold_build2 (MINUS_EXPR, itype, t,
2953 : fold_convert (itype, n1));
2954 376 : tree step = fold_convert (itype, fd->loops[j].step);
2955 376 : if (TYPE_UNSIGNED (itype)
2956 376 : && fd->loops[j].cond_code == GT_EXPR)
2957 0 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
2958 : fold_build1 (NEGATE_EXPR, itype, t),
2959 : fold_build1 (NEGATE_EXPR, itype, step));
2960 : else
2961 376 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
2962 376 : t = fold_convert (type, t);
2963 376 : t = fold_build2 (PLUS_EXPR, type, idx, t);
2964 376 : t = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
2965 : true, GSI_SAME_STMT);
2966 376 : e = make_edge (e->dest, next_bb, EDGE_FALLTHRU);
2967 376 : set_immediate_dominator (CDI_DOMINATORS, next_bb, cur_bb);
2968 376 : cond_stmt
2969 376 : = gimple_build_cond (LE_EXPR, t, stopval, NULL_TREE,
2970 : NULL_TREE);
2971 376 : gsi_insert_before (&gsi2, cond_stmt, GSI_SAME_STMT);
2972 376 : e = split_block (gsi_bb (gsi2), cond_stmt);
2973 376 : e->flags = EDGE_TRUE_VALUE;
2974 376 : e->probability = profile_probability::likely ().guessed ();
2975 376 : ne = make_edge (e->src, entry_bb, EDGE_FALSE_VALUE);
2976 376 : ne->probability = e->probability.invert ();
2977 376 : gsi2 = gsi_after_labels (e->dest);
2978 376 : expand_omp_build_assign (&gsi2, idx, t);
2979 376 : set_immediate_dominator (CDI_DOMINATORS, entry_bb, dom_bb);
2980 376 : break;
2981 : }
2982 500 : e = split_block (cur_bb, last_nondebug_stmt (cur_bb));
2983 :
2984 500 : basic_block new_cur_bb = create_empty_bb (cur_bb);
2985 500 : add_bb_to_loop (new_cur_bb, cur_bb->loop_father);
2986 :
2987 500 : gsi2 = gsi_after_labels (e->dest);
2988 500 : if (rect_p)
2989 93 : t = fold_build2 (PLUS_EXPR, type, vs[j],
2990 : build_one_cst (type));
2991 : else
2992 : {
2993 407 : tree step
2994 407 : = fold_convert (itype, unshare_expr (fd->loops[j].step));
2995 407 : if (POINTER_TYPE_P (vtype))
2996 38 : t = fold_build_pointer_plus (vs[j], step);
2997 : else
2998 369 : t = fold_build2 (PLUS_EXPR, itype, vs[j], step);
2999 : }
3000 500 : t = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
3001 : true, GSI_SAME_STMT);
3002 500 : expand_omp_build_assign (&gsi2, vs[j], t);
3003 :
3004 500 : edge ne = split_block (e->dest, last_nondebug_stmt (e->dest));
3005 500 : gsi2 = gsi_after_labels (ne->dest);
3006 :
3007 500 : gcond *cond_stmt;
3008 500 : if (next_bb == entry_bb)
3009 : /* No need to actually check the outermost condition. */
3010 376 : cond_stmt
3011 376 : = gimple_build_cond (EQ_EXPR, boolean_true_node,
3012 : boolean_true_node,
3013 : NULL_TREE, NULL_TREE);
3014 : else
3015 124 : cond_stmt
3016 155 : = gimple_build_cond (rect_p ? LT_EXPR
3017 31 : : fd->loops[j].cond_code,
3018 : vs[j], n2, NULL_TREE, NULL_TREE);
3019 500 : gsi_insert_before (&gsi2, cond_stmt, GSI_SAME_STMT);
3020 500 : edge e3, e4;
3021 500 : if (next_bb == entry_bb)
3022 : {
3023 376 : e3 = find_edge (ne->dest, next_bb);
3024 376 : e3->flags = EDGE_FALSE_VALUE;
3025 376 : dom_bb = ne->dest;
3026 : }
3027 : else
3028 124 : e3 = make_edge (ne->dest, next_bb, EDGE_FALSE_VALUE);
3029 500 : e4 = make_edge (ne->dest, new_cur_bb, EDGE_TRUE_VALUE);
3030 500 : e4->probability = profile_probability::likely ().guessed ();
3031 500 : e3->probability = e4->probability.invert ();
3032 500 : basic_block esrc = e->src;
3033 500 : make_edge (e->src, ne->dest, EDGE_FALLTHRU);
3034 500 : cur_bb = new_cur_bb;
3035 500 : basic_block latch_bb = next_bb;
3036 500 : next_bb = e->dest;
3037 500 : remove_edge (e);
3038 500 : set_immediate_dominator (CDI_DOMINATORS, ne->dest, esrc);
3039 500 : set_immediate_dominator (CDI_DOMINATORS, latch_bb, ne->dest);
3040 500 : set_immediate_dominator (CDI_DOMINATORS, cur_bb, ne->dest);
3041 : }
3042 1252 : for (int j = fd->last_nonrect; j >= fd->first_nonrect; j--)
3043 : {
3044 876 : tree vtype = TREE_TYPE (fd->loops[j].v);
3045 876 : tree itype = vtype;
3046 876 : if (POINTER_TYPE_P (itype))
3047 74 : itype = signed_type_for (itype);
3048 1752 : bool rect_p = (fd->loops[j].m1 == NULL_TREE
3049 527 : && fd->loops[j].m2 == NULL_TREE
3050 1345 : && !fd->loops[j].non_rect_referenced);
3051 876 : if (j == fd->last_nonrect)
3052 : {
3053 376 : t = fold_build2 (MINUS_EXPR, type, stopval, idx);
3054 376 : t = fold_convert (itype, t);
3055 376 : tree t2
3056 376 : = fold_convert (itype, unshare_expr (fd->loops[j].step));
3057 376 : t = fold_build2 (MULT_EXPR, itype, t, t2);
3058 376 : if (POINTER_TYPE_P (vtype))
3059 32 : t = fold_build_pointer_plus (n1, t);
3060 : else
3061 344 : t = fold_build2 (PLUS_EXPR, itype, n1, t);
3062 : }
3063 500 : else if (rect_p)
3064 : {
3065 93 : t = fold_convert (itype, vs[j]);
3066 93 : t = fold_build2 (MULT_EXPR, itype, t,
3067 : fold_convert (itype, fd->loops[j].step));
3068 93 : if (POINTER_TYPE_P (vtype))
3069 4 : t = fold_build_pointer_plus (fd->loops[j].n1, t);
3070 : else
3071 89 : t = fold_build2 (PLUS_EXPR, itype, fd->loops[j].n1, t);
3072 : }
3073 : else
3074 407 : t = vs[j];
3075 876 : t = force_gimple_operand_gsi (gsi, t, false,
3076 : NULL_TREE, true,
3077 : GSI_SAME_STMT);
3078 876 : stmt = gimple_build_assign (fd->loops[j].v, t);
3079 876 : gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3080 : }
3081 376 : if (gsi_end_p (*gsi))
3082 752 : *gsi = gsi_last_bb (gsi_bb (*gsi));
3083 : else
3084 0 : gsi_prev (gsi);
3085 376 : if (bb_triang)
3086 : {
3087 236 : e = split_block (gsi_bb (*gsi), gsi_stmt (*gsi));
3088 236 : make_edge (bb_triang, e->dest, EDGE_FALLTHRU);
3089 236 : *gsi = gsi_after_labels (e->dest);
3090 236 : if (!gsi_end_p (*gsi))
3091 0 : gsi_insert_before (gsi, gimple_build_nop (), GSI_NEW_STMT);
3092 236 : set_immediate_dominator (CDI_DOMINATORS, e->dest, bb_triang_dom);
3093 : }
3094 : }
3095 : else
3096 : {
3097 14324 : t = fold_convert (itype, t);
3098 14324 : t = fold_build2 (MULT_EXPR, itype, t,
3099 : fold_convert (itype, fd->loops[i].step));
3100 14324 : if (POINTER_TYPE_P (vtype))
3101 1617 : t = fold_build_pointer_plus (fd->loops[i].n1, t);
3102 : else
3103 12707 : t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
3104 14324 : t = force_gimple_operand_gsi (gsi, t,
3105 14324 : DECL_P (fd->loops[i].v)
3106 14324 : && TREE_ADDRESSABLE (fd->loops[i].v),
3107 : NULL_TREE, false,
3108 : GSI_CONTINUE_LINKING);
3109 14324 : stmt = gimple_build_assign (fd->loops[i].v, t);
3110 14324 : gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
3111 : }
3112 14700 : if (i != 0 && (i != fd->last_nonrect || fd->first_nonrect))
3113 : {
3114 9294 : t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
3115 9294 : t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
3116 : false, GSI_CONTINUE_LINKING);
3117 9294 : stmt = gimple_build_assign (tem, t);
3118 9294 : gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
3119 : }
3120 14700 : if (i == fd->last_nonrect)
3121 376 : i = fd->first_nonrect;
3122 : }
3123 5406 : if (fd->non_rect)
3124 1351 : for (i = 0; i <= fd->last_nonrect; i++)
3125 975 : if (fd->loops[i].m2)
3126 : {
3127 230 : tree itype = TREE_TYPE (fd->loops[i].v);
3128 :
3129 230 : tree t;
3130 230 : if (POINTER_TYPE_P (itype))
3131 : {
3132 34 : gcc_assert (integer_onep (fd->loops[i].m2));
3133 34 : t = fold_build_pointer_plus (fd->loops[i - fd->loops[i].outer].v,
3134 : unshare_expr (fd->loops[i].n2));
3135 : }
3136 : else
3137 : {
3138 196 : t = fold_convert (itype, unshare_expr (fd->loops[i].m2));
3139 196 : t = fold_build2 (MULT_EXPR, itype,
3140 : fd->loops[i - fd->loops[i].outer].v, t);
3141 196 : t = fold_build2 (PLUS_EXPR, itype, t,
3142 : fold_convert (itype,
3143 : unshare_expr (fd->loops[i].n2)));
3144 : }
3145 230 : nonrect_bounds[i] = create_tmp_reg (itype, ".bound");
3146 230 : t = force_gimple_operand_gsi (gsi, t, false,
3147 : NULL_TREE, false,
3148 : GSI_CONTINUE_LINKING);
3149 230 : stmt = gimple_build_assign (nonrect_bounds[i], t);
3150 230 : gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
3151 : }
3152 : }
3153 :
3154 : /* Helper function for expand_omp_for_*. Generate code like:
3155 : L10:
3156 : V3 += STEP3;
3157 : if (V3 cond3 N32) goto BODY_BB; else goto L11;
3158 : L11:
3159 : V3 = N31;
3160 : V2 += STEP2;
3161 : if (V2 cond2 N22) goto BODY_BB; else goto L12;
3162 : L12:
3163 : V2 = N21;
3164 : V1 += STEP1;
3165 : goto BODY_BB;
3166 : For non-rectangular loops, use temporaries stored in nonrect_bounds
3167 : for the upper bounds if M?2 multiplier is present. Given e.g.
3168 : for (V1 = N11; V1 cond1 N12; V1 += STEP1)
3169 : for (V2 = N21; V2 cond2 N22; V2 += STEP2)
3170 : for (V3 = N31; V3 cond3 N32; V3 += STEP3)
3171 : for (V4 = N41 + M41 * V2; V4 cond4 N42 + M42 * V2; V4 += STEP4)
3172 : do:
3173 : L10:
3174 : V4 += STEP4;
3175 : if (V4 cond4 NONRECT_BOUND4) goto BODY_BB; else goto L11;
3176 : L11:
3177 : V4 = N41 + M41 * V2; // This can be left out if the loop
3178 : // refers to the immediate parent loop
3179 : V3 += STEP3;
3180 : if (V3 cond3 N32) goto BODY_BB; else goto L12;
3181 : L12:
3182 : V3 = N31;
3183 : V2 += STEP2;
3184 : if (V2 cond2 N22) goto L120; else goto L13;
3185 : L120:
3186 : V4 = N41 + M41 * V2;
3187 : NONRECT_BOUND4 = N42 + M42 * V2;
3188 : if (V4 cond4 NONRECT_BOUND4) goto BODY_BB; else goto L12;
3189 : L13:
3190 : V2 = N21;
3191 : V1 += STEP1;
3192 : goto L120; */
3193 :
3194 : static basic_block
3195 2593 : extract_omp_for_update_vars (struct omp_for_data *fd, tree *nonrect_bounds,
3196 : basic_block cont_bb, basic_block body_bb)
3197 : {
3198 2593 : basic_block last_bb, bb, collapse_bb = NULL;
3199 2593 : int i;
3200 2593 : gimple_stmt_iterator gsi;
3201 2593 : edge e;
3202 2593 : tree t;
3203 2593 : gimple *stmt;
3204 :
3205 2593 : last_bb = cont_bb;
3206 9736 : for (i = fd->collapse - 1; i >= 0; i--)
3207 : {
3208 7143 : tree vtype = TREE_TYPE (fd->loops[i].v);
3209 :
3210 7143 : bb = create_empty_bb (last_bb);
3211 7143 : add_bb_to_loop (bb, last_bb->loop_father);
3212 7143 : gsi = gsi_start_bb (bb);
3213 :
3214 7143 : if (i < fd->collapse - 1)
3215 : {
3216 4550 : e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
3217 4550 : e->probability = profile_probability::guessed_always () / 8;
3218 :
3219 4550 : struct omp_for_data_loop *l = &fd->loops[i + 1];
3220 4550 : if (l->m1 == NULL_TREE || l->outer != 1)
3221 : {
3222 4342 : t = l->n1;
3223 4342 : if (l->m1)
3224 : {
3225 56 : if (POINTER_TYPE_P (TREE_TYPE (l->v)))
3226 3 : t = fold_build_pointer_plus (fd->loops[i + 1 - l->outer].v,
3227 : t);
3228 : else
3229 : {
3230 53 : tree t2
3231 53 : = fold_build2 (MULT_EXPR, TREE_TYPE (t),
3232 : fd->loops[i + 1 - l->outer].v, l->m1);
3233 53 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t2, t);
3234 : }
3235 : }
3236 4342 : t = force_gimple_operand_gsi (&gsi, t,
3237 4342 : DECL_P (l->v)
3238 4342 : && TREE_ADDRESSABLE (l->v),
3239 : NULL_TREE, false,
3240 : GSI_CONTINUE_LINKING);
3241 4342 : stmt = gimple_build_assign (l->v, t);
3242 4342 : gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3243 : }
3244 : }
3245 : else
3246 : collapse_bb = bb;
3247 :
3248 7143 : set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
3249 :
3250 7143 : if (POINTER_TYPE_P (vtype))
3251 902 : t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
3252 : else
3253 6241 : t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
3254 7143 : t = force_gimple_operand_gsi (&gsi, t,
3255 7143 : DECL_P (fd->loops[i].v)
3256 7143 : && TREE_ADDRESSABLE (fd->loops[i].v),
3257 : NULL_TREE, false, GSI_CONTINUE_LINKING);
3258 7143 : stmt = gimple_build_assign (fd->loops[i].v, t);
3259 7143 : gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3260 :
3261 7143 : if (fd->loops[i].non_rect_referenced)
3262 : {
3263 308 : basic_block update_bb = NULL, prev_bb = NULL;
3264 714 : for (int j = i + 1; j <= fd->last_nonrect; j++)
3265 406 : if (j - fd->loops[j].outer == i)
3266 : {
3267 308 : tree n1, n2;
3268 308 : struct omp_for_data_loop *l = &fd->loops[j];
3269 308 : basic_block this_bb = create_empty_bb (last_bb);
3270 308 : add_bb_to_loop (this_bb, last_bb->loop_father);
3271 308 : gimple_stmt_iterator gsi2 = gsi_start_bb (this_bb);
3272 308 : if (prev_bb)
3273 : {
3274 0 : e = make_edge (prev_bb, this_bb, EDGE_TRUE_VALUE);
3275 0 : e->probability
3276 0 : = profile_probability::guessed_always ().apply_scale (7,
3277 : 8);
3278 0 : set_immediate_dominator (CDI_DOMINATORS, this_bb, prev_bb);
3279 : }
3280 308 : if (l->m1)
3281 : {
3282 264 : if (POINTER_TYPE_P (TREE_TYPE (l->v)))
3283 26 : t = fold_build_pointer_plus (fd->loops[i].v, l->n1);
3284 : else
3285 : {
3286 238 : t = fold_build2 (MULT_EXPR, TREE_TYPE (l->m1), l->m1,
3287 : fd->loops[i].v);
3288 238 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (l->v),
3289 : t, l->n1);
3290 : }
3291 264 : n1 = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
3292 : false,
3293 : GSI_CONTINUE_LINKING);
3294 264 : stmt = gimple_build_assign (l->v, n1);
3295 264 : gsi_insert_after (&gsi2, stmt, GSI_CONTINUE_LINKING);
3296 264 : n1 = l->v;
3297 : }
3298 : else
3299 44 : n1 = force_gimple_operand_gsi (&gsi2, l->n1, true,
3300 : NULL_TREE, false,
3301 : GSI_CONTINUE_LINKING);
3302 308 : if (l->m2)
3303 : {
3304 204 : if (POINTER_TYPE_P (TREE_TYPE (l->v)))
3305 30 : t = fold_build_pointer_plus (fd->loops[i].v, l->n2);
3306 : else
3307 : {
3308 174 : t = fold_build2 (MULT_EXPR, TREE_TYPE (l->m2), l->m2,
3309 : fd->loops[i].v);
3310 174 : t = fold_build2 (PLUS_EXPR,
3311 : TREE_TYPE (nonrect_bounds[j]),
3312 : t, unshare_expr (l->n2));
3313 : }
3314 204 : n2 = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
3315 : false,
3316 : GSI_CONTINUE_LINKING);
3317 204 : stmt = gimple_build_assign (nonrect_bounds[j], n2);
3318 204 : gsi_insert_after (&gsi2, stmt, GSI_CONTINUE_LINKING);
3319 204 : n2 = nonrect_bounds[j];
3320 : }
3321 : else
3322 104 : n2 = force_gimple_operand_gsi (&gsi2, unshare_expr (l->n2),
3323 : true, NULL_TREE, false,
3324 : GSI_CONTINUE_LINKING);
3325 308 : gcond *cond_stmt
3326 308 : = gimple_build_cond (l->cond_code, n1, n2,
3327 : NULL_TREE, NULL_TREE);
3328 308 : gsi_insert_after (&gsi2, cond_stmt, GSI_CONTINUE_LINKING);
3329 308 : if (update_bb == NULL)
3330 308 : update_bb = this_bb;
3331 308 : e = make_edge (this_bb, bb, EDGE_FALSE_VALUE);
3332 308 : e->probability = profile_probability::guessed_always () / 8;
3333 308 : if (prev_bb == NULL)
3334 308 : set_immediate_dominator (CDI_DOMINATORS, this_bb, bb);
3335 308 : prev_bb = this_bb;
3336 : }
3337 308 : e = make_edge (prev_bb, body_bb, EDGE_TRUE_VALUE);
3338 308 : e->probability
3339 308 : = profile_probability::guessed_always ().apply_scale (7, 8);
3340 308 : body_bb = update_bb;
3341 : }
3342 :
3343 7143 : if (i > 0)
3344 : {
3345 4550 : if (fd->loops[i].m2)
3346 204 : t = nonrect_bounds[i];
3347 : else
3348 4346 : t = unshare_expr (fd->loops[i].n2);
3349 4550 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3350 : false, GSI_CONTINUE_LINKING);
3351 4550 : tree v = fd->loops[i].v;
3352 4550 : if (DECL_P (v) && TREE_ADDRESSABLE (v))
3353 0 : v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
3354 : false, GSI_CONTINUE_LINKING);
3355 4550 : t = build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
3356 4550 : stmt = gimple_build_cond_empty (t);
3357 4550 : gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3358 4550 : if (walk_tree (gimple_cond_lhs_ptr (as_a <gcond *> (stmt)),
3359 : expand_omp_regimplify_p, NULL, NULL)
3360 4550 : || walk_tree (gimple_cond_rhs_ptr (as_a <gcond *> (stmt)),
3361 : expand_omp_regimplify_p, NULL, NULL))
3362 4 : gimple_regimplify_operands (stmt, &gsi);
3363 4550 : e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
3364 4550 : e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
3365 : }
3366 : else
3367 2593 : make_edge (bb, body_bb, EDGE_FALLTHRU);
3368 7143 : set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
3369 7143 : last_bb = bb;
3370 : }
3371 :
3372 2593 : return collapse_bb;
3373 : }
3374 :
3375 : /* Expand #pragma omp ordered depend(source). */
3376 :
3377 : static void
3378 335 : expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
3379 : tree *counts, location_t loc)
3380 : {
3381 56 : enum built_in_function source_ix
3382 335 : = fd->iter_type == long_integer_type_node
3383 335 : ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
3384 335 : gimple *g
3385 335 : = gimple_build_call (builtin_decl_explicit (source_ix), 1,
3386 335 : build_fold_addr_expr (counts[fd->ordered]));
3387 335 : gimple_set_location (g, loc);
3388 335 : gsi_insert_before (gsi, g, GSI_SAME_STMT);
3389 335 : }
3390 :
3391 : /* Expand a single depend from #pragma omp ordered depend(sink:...). */
3392 :
3393 : static void
3394 466 : expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
3395 : tree *counts, tree c, location_t loc,
3396 : basic_block cont_bb)
3397 : {
3398 466 : auto_vec<tree, 10> args;
3399 73 : enum built_in_function sink_ix
3400 466 : = fd->iter_type == long_integer_type_node
3401 466 : ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
3402 466 : tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
3403 466 : int i;
3404 466 : gimple_stmt_iterator gsi2 = *gsi;
3405 466 : bool warned_step = false;
3406 :
3407 466 : if (deps == NULL)
3408 : {
3409 : /* Handle doacross(sink: omp_cur_iteration - 1). */
3410 52 : gsi_prev (&gsi2);
3411 52 : edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
3412 52 : edge e2 = split_block_after_labels (e1->dest);
3413 52 : gsi2 = gsi_after_labels (e1->dest);
3414 52 : *gsi = gsi_last_bb (e1->src);
3415 52 : gimple_stmt_iterator gsi3 = *gsi;
3416 :
3417 52 : if (counts[fd->collapse - 1])
3418 : {
3419 8 : gcc_assert (fd->collapse == 1);
3420 8 : t = counts[fd->collapse - 1];
3421 : }
3422 44 : else if (fd->collapse > 1)
3423 28 : t = fd->loop.v;
3424 : else
3425 : {
3426 16 : t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
3427 : fd->loops[0].v, fd->loops[0].n1);
3428 16 : t = fold_convert (fd->iter_type, t);
3429 : }
3430 :
3431 52 : t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
3432 : false, GSI_CONTINUE_LINKING);
3433 52 : gsi_insert_after (gsi, gimple_build_cond (NE_EXPR, t,
3434 52 : build_zero_cst (TREE_TYPE (t)),
3435 : NULL_TREE, NULL_TREE),
3436 : GSI_NEW_STMT);
3437 :
3438 52 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
3439 : build_minus_one_cst (TREE_TYPE (t)));
3440 52 : t = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
3441 : true, GSI_SAME_STMT);
3442 52 : args.safe_push (t);
3443 281 : for (i = fd->collapse; i < fd->ordered; i++)
3444 : {
3445 229 : t = counts[fd->ordered + 2 + (i - fd->collapse)];
3446 229 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
3447 : build_minus_one_cst (TREE_TYPE (t)));
3448 229 : t = fold_convert (fd->iter_type, t);
3449 229 : t = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
3450 : true, GSI_SAME_STMT);
3451 229 : args.safe_push (t);
3452 : }
3453 :
3454 52 : gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix),
3455 : args);
3456 52 : gimple_set_location (g, loc);
3457 52 : gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
3458 :
3459 52 : edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
3460 52 : e3->probability = profile_probability::guessed_always () / 8;
3461 52 : e1->probability = e3->probability.invert ();
3462 52 : e1->flags = EDGE_TRUE_VALUE;
3463 52 : set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
3464 :
3465 52 : if (fd->ordered > fd->collapse && cont_bb)
3466 : {
3467 33 : if (counts[fd->ordered + 1] == NULL_TREE)
3468 33 : counts[fd->ordered + 1]
3469 33 : = create_tmp_var (boolean_type_node, ".first");
3470 :
3471 33 : edge e4;
3472 33 : if (gsi_end_p (gsi3))
3473 25 : e4 = split_block_after_labels (e1->src);
3474 : else
3475 : {
3476 8 : gsi_prev (&gsi3);
3477 8 : e4 = split_block (gsi_bb (gsi3), gsi_stmt (gsi3));
3478 : }
3479 33 : gsi3 = gsi_last_bb (e4->src);
3480 :
3481 33 : gsi_insert_after (&gsi3,
3482 33 : gimple_build_cond (NE_EXPR,
3483 33 : counts[fd->ordered + 1],
3484 : boolean_false_node,
3485 : NULL_TREE, NULL_TREE),
3486 : GSI_NEW_STMT);
3487 :
3488 33 : edge e5 = make_edge (e4->src, e2->dest, EDGE_FALSE_VALUE);
3489 33 : e4->probability = profile_probability::guessed_always () / 8;
3490 33 : e5->probability = e4->probability.invert ();
3491 33 : e4->flags = EDGE_TRUE_VALUE;
3492 33 : set_immediate_dominator (CDI_DOMINATORS, e2->dest, e4->src);
3493 : }
3494 :
3495 52 : *gsi = gsi_after_labels (e2->dest);
3496 52 : return;
3497 : }
3498 504 : for (i = 0; i < fd->ordered; i++)
3499 : {
3500 502 : tree step = NULL_TREE;
3501 502 : off = TREE_PURPOSE (deps);
3502 502 : if (TREE_CODE (off) == TRUNC_DIV_EXPR)
3503 : {
3504 83 : step = TREE_OPERAND (off, 1);
3505 83 : off = TREE_OPERAND (off, 0);
3506 : }
3507 502 : if (!integer_zerop (off))
3508 : {
3509 412 : gcc_assert (fd->loops[i].cond_code == LT_EXPR
3510 : || fd->loops[i].cond_code == GT_EXPR);
3511 412 : bool forward = fd->loops[i].cond_code == LT_EXPR;
3512 412 : if (step)
3513 : {
3514 : /* Non-simple Fortran DO loops. If step is variable,
3515 : we don't know at compile even the direction, so can't
3516 : warn. */
3517 83 : if (TREE_CODE (step) != INTEGER_CST)
3518 : break;
3519 0 : forward = tree_int_cst_sgn (step) != -1;
3520 : }
3521 329 : if (forward ^ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
3522 17 : warning_at (loc, OPT_Wopenmp,
3523 : "%qs clause with %<sink%> modifier "
3524 : "waiting for lexically later iteration",
3525 17 : OMP_CLAUSE_DOACROSS_DEPEND (c)
3526 : ? "depend" : "doacross");
3527 : break;
3528 : }
3529 90 : deps = TREE_CHAIN (deps);
3530 : }
3531 : /* If all offsets corresponding to the collapsed loops are zero,
3532 : this depend clause can be ignored. FIXME: but there is still a
3533 : flush needed. We need to emit one __sync_synchronize () for it
3534 : though (perhaps conditionally)? Solve this together with the
3535 : conservative dependence folding optimization.
3536 : if (i >= fd->collapse)
3537 : return; */
3538 :
3539 414 : deps = OMP_CLAUSE_DECL (c);
3540 414 : gsi_prev (&gsi2);
3541 414 : edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
3542 414 : edge e2 = split_block_after_labels (e1->dest);
3543 :
3544 414 : gsi2 = gsi_after_labels (e1->dest);
3545 414 : *gsi = gsi_last_bb (e1->src);
3546 2806 : for (i = 0; i < fd->ordered; i++)
3547 : {
3548 2392 : tree itype = TREE_TYPE (fd->loops[i].v);
3549 2392 : tree step = NULL_TREE;
3550 2392 : tree orig_off = NULL_TREE;
3551 2392 : if (POINTER_TYPE_P (itype))
3552 9 : itype = sizetype;
3553 2392 : if (i)
3554 1978 : deps = TREE_CHAIN (deps);
3555 2392 : off = TREE_PURPOSE (deps);
3556 2392 : if (TREE_CODE (off) == TRUNC_DIV_EXPR)
3557 : {
3558 204 : step = TREE_OPERAND (off, 1);
3559 204 : off = TREE_OPERAND (off, 0);
3560 204 : gcc_assert (fd->loops[i].cond_code == LT_EXPR
3561 : && integer_onep (fd->loops[i].step)
3562 : && !POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)));
3563 : }
3564 2392 : tree s = fold_convert_loc (loc, itype, step ? step : fd->loops[i].step);
3565 2392 : if (step)
3566 : {
3567 204 : off = fold_convert_loc (loc, itype, off);
3568 204 : orig_off = off;
3569 204 : off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
3570 : }
3571 :
3572 2392 : if (integer_zerop (off))
3573 1516 : t = boolean_true_node;
3574 : else
3575 : {
3576 876 : tree a;
3577 876 : tree co = fold_convert_loc (loc, itype, off);
3578 876 : if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
3579 : {
3580 9 : if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
3581 0 : co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
3582 9 : a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
3583 9 : TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
3584 : co);
3585 : }
3586 867 : else if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
3587 640 : a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
3588 : fd->loops[i].v, co);
3589 : else
3590 227 : a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
3591 : fd->loops[i].v, co);
3592 876 : if (step)
3593 : {
3594 204 : tree t1, t2;
3595 204 : if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
3596 149 : t1 = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
3597 149 : fd->loops[i].n1);
3598 : else
3599 55 : t1 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
3600 55 : fd->loops[i].n2);
3601 204 : if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
3602 149 : t2 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
3603 149 : fd->loops[i].n2);
3604 : else
3605 55 : t2 = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
3606 55 : fd->loops[i].n1);
3607 204 : t = fold_build2_loc (loc, LT_EXPR, boolean_type_node,
3608 204 : step, build_int_cst (TREE_TYPE (step), 0));
3609 204 : if (TREE_CODE (step) != INTEGER_CST)
3610 : {
3611 204 : t1 = unshare_expr (t1);
3612 204 : t1 = force_gimple_operand_gsi (gsi, t1, true, NULL_TREE,
3613 : false, GSI_CONTINUE_LINKING);
3614 204 : t2 = unshare_expr (t2);
3615 204 : t2 = force_gimple_operand_gsi (gsi, t2, true, NULL_TREE,
3616 : false, GSI_CONTINUE_LINKING);
3617 : }
3618 204 : t = fold_build3_loc (loc, COND_EXPR, boolean_type_node,
3619 : t, t2, t1);
3620 : }
3621 672 : else if (fd->loops[i].cond_code == LT_EXPR)
3622 : {
3623 520 : if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
3624 433 : t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
3625 : fd->loops[i].n1);
3626 : else
3627 87 : t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
3628 : fd->loops[i].n2);
3629 : }
3630 152 : else if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
3631 58 : t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
3632 : fd->loops[i].n2);
3633 : else
3634 94 : t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
3635 : fd->loops[i].n1);
3636 : }
3637 2392 : if (cond)
3638 1978 : cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
3639 : else
3640 414 : cond = t;
3641 :
3642 2392 : off = fold_convert_loc (loc, itype, off);
3643 :
3644 2392 : if (step
3645 4411 : || (fd->loops[i].cond_code == LT_EXPR
3646 2188 : ? !integer_onep (fd->loops[i].step)
3647 169 : : !integer_minus_onep (fd->loops[i].step)))
3648 : {
3649 382 : if (step == NULL_TREE
3650 178 : && TYPE_UNSIGNED (itype)
3651 393 : && fd->loops[i].cond_code == GT_EXPR)
3652 9 : t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
3653 : fold_build1_loc (loc, NEGATE_EXPR, itype,
3654 : s));
3655 : else
3656 542 : t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype,
3657 : orig_off ? orig_off : off, s);
3658 382 : t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
3659 : build_int_cst (itype, 0));
3660 382 : if (integer_zerop (t) && !warned_step)
3661 : {
3662 5 : warning_at (loc, OPT_Wopenmp,
3663 : "%qs clause with %<sink%> modifier refers to "
3664 : "iteration never in the iteration space",
3665 5 : OMP_CLAUSE_DOACROSS_DEPEND (c)
3666 : ? "depend" : "doacross");
3667 5 : warned_step = true;
3668 : }
3669 382 : cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
3670 : cond, t);
3671 : }
3672 :
3673 2392 : if (i <= fd->collapse - 1 && fd->collapse > 1)
3674 322 : t = fd->loop.v;
3675 2070 : else if (counts[i])
3676 166 : t = counts[i];
3677 : else
3678 : {
3679 1904 : t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
3680 1904 : fd->loops[i].v, fd->loops[i].n1);
3681 1904 : t = fold_convert_loc (loc, fd->iter_type, t);
3682 : }
3683 2392 : if (step)
3684 : /* We have divided off by step already earlier. */;
3685 2188 : else if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
3686 9 : off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
3687 : fold_build1_loc (loc, NEGATE_EXPR, itype,
3688 : s));
3689 : else
3690 2179 : off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
3691 2392 : if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
3692 640 : off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
3693 2392 : off = fold_convert_loc (loc, fd->iter_type, off);
3694 2392 : if (i <= fd->collapse - 1 && fd->collapse > 1)
3695 : {
3696 322 : if (i)
3697 161 : off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
3698 : off);
3699 322 : if (i < fd->collapse - 1)
3700 : {
3701 322 : coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
3702 161 : counts[i]);
3703 161 : continue;
3704 : }
3705 : }
3706 2231 : off = unshare_expr (off);
3707 2231 : t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
3708 2231 : t = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
3709 : true, GSI_SAME_STMT);
3710 2231 : args.safe_push (t);
3711 : }
3712 414 : gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
3713 414 : gimple_set_location (g, loc);
3714 414 : gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
3715 :
3716 414 : cond = unshare_expr (cond);
3717 414 : cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
3718 : GSI_CONTINUE_LINKING);
3719 414 : gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
3720 414 : edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
3721 414 : e3->probability = profile_probability::guessed_always () / 8;
3722 414 : e1->probability = e3->probability.invert ();
3723 414 : e1->flags = EDGE_TRUE_VALUE;
3724 414 : set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
3725 :
3726 414 : *gsi = gsi_after_labels (e2->dest);
3727 466 : }
3728 :
3729 : /* Expand all #pragma omp ordered depend(source) and
3730 : #pragma omp ordered depend(sink:...) constructs in the current
3731 : #pragma omp for ordered(n) region. */
3732 :
3733 : static void
3734 335 : expand_omp_ordered_source_sink (struct omp_region *region,
3735 : struct omp_for_data *fd, tree *counts,
3736 : basic_block cont_bb)
3737 : {
3738 335 : struct omp_region *inner;
3739 335 : int i;
3740 1563 : for (i = fd->collapse - 1; i < fd->ordered; i++)
3741 1228 : if (i == fd->collapse - 1 && fd->collapse > 1)
3742 147 : counts[i] = NULL_TREE;
3743 1081 : else if (i >= fd->collapse && !cont_bb)
3744 0 : counts[i] = build_zero_cst (fd->iter_type);
3745 2154 : else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
3746 2154 : && integer_onep (fd->loops[i].step))
3747 987 : counts[i] = NULL_TREE;
3748 : else
3749 94 : counts[i] = create_tmp_var (fd->iter_type, ".orditer");
3750 335 : tree atype
3751 335 : = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
3752 335 : counts[fd->ordered] = create_tmp_var (atype, ".orditera");
3753 335 : TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
3754 335 : counts[fd->ordered + 1] = NULL_TREE;
3755 :
3756 1615 : for (inner = region->inner; inner; inner = inner->next)
3757 1280 : if (inner->type == GIMPLE_OMP_ORDERED)
3758 : {
3759 709 : gomp_ordered *ord_stmt = inner->ord_stmt;
3760 709 : gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
3761 709 : location_t loc = gimple_location (ord_stmt);
3762 709 : tree c;
3763 1175 : for (c = gimple_omp_ordered_clauses (ord_stmt);
3764 1175 : c; c = OMP_CLAUSE_CHAIN (c))
3765 801 : if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
3766 : break;
3767 709 : if (c)
3768 335 : expand_omp_ordered_source (&gsi, fd, counts, loc);
3769 1510 : for (c = gimple_omp_ordered_clauses (ord_stmt);
3770 1510 : c; c = OMP_CLAUSE_CHAIN (c))
3771 801 : if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
3772 466 : expand_omp_ordered_sink (&gsi, fd, counts, c, loc, cont_bb);
3773 709 : gsi_remove (&gsi, true);
3774 : }
3775 335 : }
3776 :
3777 : /* Wrap the body into fd->ordered - fd->collapse loops that aren't
3778 : collapsed. */
3779 :
3780 : static basic_block
3781 335 : expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
3782 : basic_block cont_bb, basic_block body_bb,
3783 : basic_block l0_bb, bool ordered_lastprivate)
3784 : {
3785 335 : if (fd->ordered == fd->collapse)
3786 : return cont_bb;
3787 :
3788 171 : if (!cont_bb)
3789 : {
3790 0 : gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
3791 0 : for (int i = fd->collapse; i < fd->ordered; i++)
3792 : {
3793 0 : tree type = TREE_TYPE (fd->loops[i].v);
3794 0 : tree n1 = fold_convert (type, fd->loops[i].n1);
3795 0 : expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
3796 0 : tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
3797 0 : size_int (i - fd->collapse + 1),
3798 : NULL_TREE, NULL_TREE);
3799 0 : expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
3800 : }
3801 0 : return NULL;
3802 : }
3803 :
3804 1064 : for (int i = fd->ordered - 1; i >= fd->collapse; i--)
3805 : {
3806 893 : tree t, type = TREE_TYPE (fd->loops[i].v);
3807 893 : gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
3808 893 : if (counts[fd->ordered + 1] && i == fd->collapse)
3809 33 : expand_omp_build_assign (&gsi, counts[fd->ordered + 1],
3810 : boolean_true_node);
3811 893 : expand_omp_build_assign (&gsi, fd->loops[i].v,
3812 893 : fold_convert (type, fd->loops[i].n1));
3813 893 : if (counts[i])
3814 57 : expand_omp_build_assign (&gsi, counts[i],
3815 : build_zero_cst (fd->iter_type));
3816 893 : tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
3817 893 : size_int (i - fd->collapse + 1),
3818 : NULL_TREE, NULL_TREE);
3819 893 : expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
3820 893 : if (!gsi_end_p (gsi))
3821 893 : gsi_prev (&gsi);
3822 : else
3823 0 : gsi = gsi_last_bb (body_bb);
3824 893 : edge e1 = split_block (body_bb, gsi_stmt (gsi));
3825 893 : basic_block new_body = e1->dest;
3826 893 : if (body_bb == cont_bb)
3827 0 : cont_bb = new_body;
3828 893 : edge e2 = NULL;
3829 893 : basic_block new_header;
3830 893 : if (EDGE_COUNT (cont_bb->preds) > 0)
3831 : {
3832 864 : gsi = gsi_last_bb (cont_bb);
3833 864 : if (POINTER_TYPE_P (type))
3834 0 : t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
3835 : else
3836 864 : t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
3837 : fold_convert (type, fd->loops[i].step));
3838 864 : expand_omp_build_assign (&gsi, fd->loops[i].v, t);
3839 864 : if (counts[i])
3840 : {
3841 57 : t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
3842 : build_int_cst (fd->iter_type, 1));
3843 57 : expand_omp_build_assign (&gsi, counts[i], t);
3844 57 : t = counts[i];
3845 : }
3846 : else
3847 : {
3848 807 : t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
3849 : fd->loops[i].v, fd->loops[i].n1);
3850 807 : t = fold_convert (fd->iter_type, t);
3851 807 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3852 : true, GSI_SAME_STMT);
3853 : }
3854 864 : aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
3855 864 : size_int (i - fd->collapse + 1),
3856 : NULL_TREE, NULL_TREE);
3857 864 : expand_omp_build_assign (&gsi, aref, t);
3858 864 : if (counts[fd->ordered + 1] && i == fd->ordered - 1)
3859 30 : expand_omp_build_assign (&gsi, counts[fd->ordered + 1],
3860 : boolean_false_node);
3861 864 : gsi_prev (&gsi);
3862 864 : e2 = split_block (cont_bb, gsi_stmt (gsi));
3863 864 : new_header = e2->dest;
3864 : }
3865 : else
3866 : new_header = cont_bb;
3867 893 : gsi = gsi_after_labels (new_header);
3868 893 : tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
3869 : true, GSI_SAME_STMT);
3870 893 : tree n2
3871 893 : = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
3872 : true, NULL_TREE, true, GSI_SAME_STMT);
3873 893 : t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
3874 893 : gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
3875 893 : edge e3 = split_block (new_header, gsi_stmt (gsi));
3876 893 : cont_bb = e3->dest;
3877 893 : remove_edge (e1);
3878 893 : make_edge (body_bb, new_header, EDGE_FALLTHRU);
3879 893 : e3->flags = EDGE_FALSE_VALUE;
3880 893 : e3->probability = profile_probability::guessed_always () / 8;
3881 893 : e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
3882 893 : e1->probability = e3->probability.invert ();
3883 :
3884 893 : set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
3885 893 : set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
3886 :
3887 893 : if (e2)
3888 : {
3889 864 : class loop *loop = alloc_loop ();
3890 864 : loop->header = new_header;
3891 864 : loop->latch = e2->src;
3892 864 : add_loop (loop, l0_bb->loop_father);
3893 : }
3894 : }
3895 :
3896 : /* If there are any lastprivate clauses and it is possible some loops
3897 : might have zero iterations, ensure all the decls are initialized,
3898 : otherwise we could crash evaluating C++ class iterators with lastprivate
3899 : clauses. */
3900 : bool need_inits = false;
3901 171 : for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
3902 0 : if (need_inits)
3903 : {
3904 0 : tree type = TREE_TYPE (fd->loops[i].v);
3905 0 : gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
3906 0 : expand_omp_build_assign (&gsi, fd->loops[i].v,
3907 : fold_convert (type, fd->loops[i].n1));
3908 : }
3909 : else
3910 : {
3911 0 : tree type = TREE_TYPE (fd->loops[i].v);
3912 0 : tree this_cond = fold_build2 (fd->loops[i].cond_code,
3913 : boolean_type_node,
3914 : fold_convert (type, fd->loops[i].n1),
3915 : fold_convert (type, fd->loops[i].n2));
3916 0 : if (!integer_onep (this_cond))
3917 0 : need_inits = true;
3918 : }
3919 :
3920 : return cont_bb;
3921 : }
3922 :
3923 : /* A subroutine of expand_omp_for. Generate code for a parallel
3924 : loop with any schedule. Given parameters:
3925 :
3926 : for (V = N1; V cond N2; V += STEP) BODY;
3927 :
3928 : where COND is "<" or ">", we generate pseudocode
3929 :
3930 : more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
3931 : if (more) goto L0; else goto L3;
3932 : L0:
3933 : V = istart0;
3934 : iend = iend0;
3935 : L1:
3936 : BODY;
3937 : V += STEP;
3938 : if (V cond iend) goto L1; else goto L2;
3939 : L2:
3940 : if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3941 : L3:
3942 :
3943 : If this is a combined omp parallel loop, instead of the call to
3944 : GOMP_loop_foo_start, we call GOMP_loop_foo_next.
3945 : If this is gimple_omp_for_combined_p loop, then instead of assigning
3946 : V and iend in L0 we assign the first two _looptemp_ clause decls of the
3947 : inner GIMPLE_OMP_FOR and V += STEP; and
3948 : if (V cond iend) goto L1; else goto L2; are removed.
3949 :
3950 : For collapsed loops, given parameters:
3951 : collapse(3)
3952 : for (V1 = N11; V1 cond1 N12; V1 += STEP1)
3953 : for (V2 = N21; V2 cond2 N22; V2 += STEP2)
3954 : for (V3 = N31; V3 cond3 N32; V3 += STEP3)
3955 : BODY;
3956 :
3957 : we generate pseudocode
3958 :
3959 : if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
3960 : if (cond3 is <)
3961 : adj = STEP3 - 1;
3962 : else
3963 : adj = STEP3 + 1;
3964 : count3 = (adj + N32 - N31) / STEP3;
3965 : if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
3966 : if (cond2 is <)
3967 : adj = STEP2 - 1;
3968 : else
3969 : adj = STEP2 + 1;
3970 : count2 = (adj + N22 - N21) / STEP2;
3971 : if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
3972 : if (cond1 is <)
3973 : adj = STEP1 - 1;
3974 : else
3975 : adj = STEP1 + 1;
3976 : count1 = (adj + N12 - N11) / STEP1;
3977 : count = count1 * count2 * count3;
3978 : goto Z1;
3979 : Z0:
3980 : count = 0;
3981 : Z1:
3982 : more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
3983 : if (more) goto L0; else goto L3;
3984 : L0:
3985 : V = istart0;
3986 : T = V;
3987 : V3 = N31 + (T % count3) * STEP3;
3988 : T = T / count3;
3989 : V2 = N21 + (T % count2) * STEP2;
3990 : T = T / count2;
3991 : V1 = N11 + T * STEP1;
3992 : iend = iend0;
3993 : L1:
3994 : BODY;
3995 : V += 1;
3996 : if (V < iend) goto L10; else goto L2;
3997 : L10:
3998 : V3 += STEP3;
3999 : if (V3 cond3 N32) goto L1; else goto L11;
4000 : L11:
4001 : V3 = N31;
4002 : V2 += STEP2;
4003 : if (V2 cond2 N22) goto L1; else goto L12;
4004 : L12:
4005 : V2 = N21;
4006 : V1 += STEP1;
4007 : goto L1;
4008 : L2:
4009 : if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
4010 : L3:
4011 :
4012 : */
4013 :
4014 : static void
4015 4134 : expand_omp_for_generic (struct omp_region *region,
4016 : struct omp_for_data *fd,
4017 : enum built_in_function start_fn,
4018 : enum built_in_function next_fn,
4019 : tree sched_arg,
4020 : gimple *inner_stmt)
4021 : {
4022 4134 : tree type, istart0, iend0, iend;
4023 4134 : tree t, vmain, vback, bias = NULL_TREE;
4024 4134 : basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
4025 4134 : basic_block l2_bb = NULL, l3_bb = NULL;
4026 4134 : gimple_stmt_iterator gsi;
4027 4134 : gassign *assign_stmt;
4028 4134 : bool in_combined_parallel = is_combined_parallel (region);
4029 4134 : bool broken_loop = region->cont == NULL;
4030 4134 : edge e, ne;
4031 4134 : tree *counts = NULL;
4032 4134 : int i;
4033 4134 : bool ordered_lastprivate = false;
4034 4134 : bool offload = is_in_offload_region (region);
4035 :
4036 4134 : gcc_assert (!broken_loop || !in_combined_parallel);
4037 4134 : gcc_assert (fd->iter_type == long_integer_type_node
4038 : || !in_combined_parallel);
4039 :
4040 4134 : entry_bb = region->entry;
4041 4134 : cont_bb = region->cont;
4042 4134 : collapse_bb = NULL;
4043 4134 : gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
4044 4134 : gcc_assert (broken_loop
4045 : || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
4046 4134 : l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
4047 4134 : l1_bb = single_succ (l0_bb);
4048 4134 : if (!broken_loop)
4049 : {
4050 3727 : l2_bb = create_empty_bb (cont_bb);
4051 3727 : gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
4052 : || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
4053 : == l1_bb));
4054 3727 : gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4055 : }
4056 : else
4057 : l2_bb = NULL;
4058 4134 : l3_bb = BRANCH_EDGE (entry_bb)->dest;
4059 4134 : exit_bb = region->exit;
4060 :
4061 4134 : gsi = gsi_last_nondebug_bb (entry_bb);
4062 :
4063 4134 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4064 4134 : if (fd->ordered
4065 4134 : && omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
4066 : OMP_CLAUSE_LASTPRIVATE))
4067 4134 : ordered_lastprivate = false;
4068 4134 : tree reductions = NULL_TREE;
4069 4134 : tree mem = NULL_TREE, cond_var = NULL_TREE, condtemp = NULL_TREE;
4070 4134 : tree memv = NULL_TREE;
4071 4134 : if (fd->lastprivate_conditional)
4072 : {
4073 46 : tree c = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
4074 : OMP_CLAUSE__CONDTEMP_);
4075 46 : if (fd->have_pointer_condtemp)
4076 28 : condtemp = OMP_CLAUSE_DECL (c);
4077 46 : c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE__CONDTEMP_);
4078 46 : cond_var = OMP_CLAUSE_DECL (c);
4079 : }
4080 4134 : if (sched_arg)
4081 : {
4082 169 : if (fd->have_reductemp)
4083 : {
4084 149 : tree c = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
4085 : OMP_CLAUSE__REDUCTEMP_);
4086 149 : reductions = OMP_CLAUSE_DECL (c);
4087 149 : gcc_assert (TREE_CODE (reductions) == SSA_NAME);
4088 149 : gimple *g = SSA_NAME_DEF_STMT (reductions);
4089 149 : reductions = gimple_assign_rhs1 (g);
4090 149 : OMP_CLAUSE_DECL (c) = reductions;
4091 149 : entry_bb = gimple_bb (g);
4092 149 : edge e = split_block (entry_bb, g);
4093 149 : if (region->entry == entry_bb)
4094 8 : region->entry = e->dest;
4095 298 : gsi = gsi_last_bb (entry_bb);
4096 : }
4097 : else
4098 20 : reductions = null_pointer_node;
4099 169 : if (fd->have_pointer_condtemp)
4100 : {
4101 28 : tree type = TREE_TYPE (condtemp);
4102 28 : memv = create_tmp_var (type);
4103 28 : TREE_ADDRESSABLE (memv) = 1;
4104 28 : unsigned HOST_WIDE_INT sz
4105 28 : = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
4106 28 : sz *= fd->lastprivate_conditional;
4107 28 : expand_omp_build_assign (&gsi, memv, build_int_cst (type, sz),
4108 : false);
4109 28 : mem = build_fold_addr_expr (memv);
4110 : }
4111 : else
4112 141 : mem = null_pointer_node;
4113 : }
4114 4134 : if (fd->collapse > 1 || fd->ordered)
4115 : {
4116 1669 : int first_zero_iter1 = -1, first_zero_iter2 = -1;
4117 1669 : basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
4118 :
4119 1669 : counts = XALLOCAVEC (tree, fd->ordered
4120 : ? fd->ordered + 2
4121 : + (fd->ordered - fd->collapse)
4122 : : fd->collapse);
4123 1669 : expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
4124 : zero_iter1_bb, first_zero_iter1,
4125 : zero_iter2_bb, first_zero_iter2, l2_dom_bb);
4126 :
4127 1669 : if (zero_iter1_bb)
4128 : {
4129 : /* Some counts[i] vars might be uninitialized if
4130 : some loop has zero iterations. But the body shouldn't
4131 : be executed in that case, so just avoid uninit warnings. */
4132 1913 : for (i = first_zero_iter1;
4133 1913 : i < (fd->ordered ? fd->ordered : fd->collapse); i++)
4134 1502 : if (SSA_VAR_P (counts[i]))
4135 950 : suppress_warning (counts[i], OPT_Wuninitialized);
4136 411 : gsi_prev (&gsi);
4137 411 : e = split_block (entry_bb, gsi_stmt (gsi));
4138 411 : entry_bb = e->dest;
4139 411 : make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
4140 411 : gsi = gsi_last_nondebug_bb (entry_bb);
4141 411 : set_immediate_dominator (CDI_DOMINATORS, entry_bb,
4142 : get_immediate_dominator (CDI_DOMINATORS,
4143 : zero_iter1_bb));
4144 : }
4145 1669 : if (zero_iter2_bb)
4146 : {
4147 : /* Some counts[i] vars might be uninitialized if
4148 : some loop has zero iterations. But the body shouldn't
4149 : be executed in that case, so just avoid uninit warnings. */
4150 394 : for (i = first_zero_iter2; i < fd->ordered; i++)
4151 276 : if (SSA_VAR_P (counts[i]))
4152 216 : suppress_warning (counts[i], OPT_Wuninitialized);
4153 118 : if (zero_iter1_bb)
4154 103 : make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
4155 : else
4156 : {
4157 15 : gsi_prev (&gsi);
4158 15 : e = split_block (entry_bb, gsi_stmt (gsi));
4159 15 : entry_bb = e->dest;
4160 15 : make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
4161 15 : gsi = gsi_last_nondebug_bb (entry_bb);
4162 15 : set_immediate_dominator (CDI_DOMINATORS, entry_bb,
4163 : get_immediate_dominator
4164 : (CDI_DOMINATORS, zero_iter2_bb));
4165 : }
4166 : }
4167 1669 : if (fd->collapse == 1)
4168 : {
4169 188 : counts[0] = fd->loop.n2;
4170 188 : fd->loop = fd->loops[0];
4171 : }
4172 : }
4173 :
4174 4134 : type = TREE_TYPE (fd->loop.v);
4175 4134 : istart0 = create_tmp_var (fd->iter_type, ".istart0");
4176 4134 : iend0 = create_tmp_var (fd->iter_type, ".iend0");
4177 4134 : TREE_ADDRESSABLE (istart0) = 1;
4178 4134 : TREE_ADDRESSABLE (iend0) = 1;
4179 :
4180 : /* See if we need to bias by LLONG_MIN. */
4181 4134 : if (fd->iter_type == long_long_unsigned_type_node
4182 778 : && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == BITINT_TYPE)
4183 530 : && !TYPE_UNSIGNED (type)
4184 4134 : && fd->ordered == 0)
4185 : {
4186 0 : tree n1, n2;
4187 :
4188 0 : if (fd->loop.cond_code == LT_EXPR)
4189 : {
4190 0 : n1 = fd->loop.n1;
4191 0 : n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
4192 : }
4193 : else
4194 : {
4195 0 : n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
4196 0 : n2 = fd->loop.n1;
4197 : }
4198 0 : if (TREE_CODE (n1) != INTEGER_CST
4199 0 : || TREE_CODE (n2) != INTEGER_CST
4200 0 : || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
4201 0 : bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
4202 : }
4203 :
4204 4134 : gimple_stmt_iterator gsif = gsi;
4205 4134 : gsi_prev (&gsif);
4206 :
4207 4134 : tree arr = NULL_TREE;
4208 4134 : if (in_combined_parallel)
4209 : {
4210 1084 : gcc_assert (fd->ordered == 0);
4211 : /* In a combined parallel loop, emit a call to
4212 : GOMP_loop_foo_next. */
4213 1084 : t = build_call_expr (builtin_decl_explicit (next_fn), 2,
4214 : build_fold_addr_expr (istart0),
4215 : build_fold_addr_expr (iend0));
4216 : }
4217 : else
4218 : {
4219 3050 : tree t0, t1, t2, t3, t4;
4220 : /* If this is not a combined parallel loop, emit a call to
4221 : GOMP_loop_foo_start in ENTRY_BB. */
4222 3050 : t4 = build_fold_addr_expr (iend0);
4223 3050 : t3 = build_fold_addr_expr (istart0);
4224 3050 : if (fd->ordered)
4225 : {
4226 670 : t0 = build_int_cst (unsigned_type_node,
4227 335 : fd->ordered - fd->collapse + 1);
4228 335 : arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
4229 335 : fd->ordered
4230 335 : - fd->collapse + 1),
4231 : ".omp_counts");
4232 335 : DECL_NAMELESS (arr) = 1;
4233 335 : TREE_ADDRESSABLE (arr) = 1;
4234 335 : TREE_STATIC (arr) = 1;
4235 335 : vec<constructor_elt, va_gc> *v;
4236 335 : vec_alloc (v, fd->ordered - fd->collapse + 1);
4237 335 : int idx;
4238 :
4239 1898 : for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
4240 : {
4241 1228 : tree c;
4242 1228 : if (idx == 0 && fd->collapse > 1)
4243 147 : c = fd->loop.n2;
4244 : else
4245 1081 : c = counts[idx + fd->collapse - 1];
4246 1228 : tree purpose = size_int (idx);
4247 1228 : CONSTRUCTOR_APPEND_ELT (v, purpose, c);
4248 1228 : if (TREE_CODE (c) != INTEGER_CST)
4249 433 : TREE_STATIC (arr) = 0;
4250 : }
4251 :
4252 335 : DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
4253 335 : if (!TREE_STATIC (arr))
4254 232 : force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
4255 : void_type_node, arr),
4256 : true, NULL_TREE, true, GSI_SAME_STMT);
4257 335 : t1 = build_fold_addr_expr (arr);
4258 335 : t2 = NULL_TREE;
4259 : }
4260 : else
4261 : {
4262 2715 : t2 = fold_convert (fd->iter_type, fd->loop.step);
4263 2715 : t1 = fd->loop.n2;
4264 2715 : t0 = fd->loop.n1;
4265 2715 : if (gimple_omp_for_combined_into_p (fd->for_stmt))
4266 : {
4267 1152 : tree innerc
4268 1152 : = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
4269 : OMP_CLAUSE__LOOPTEMP_);
4270 1152 : gcc_assert (innerc);
4271 1152 : t0 = OMP_CLAUSE_DECL (innerc);
4272 1152 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
4273 : OMP_CLAUSE__LOOPTEMP_);
4274 1152 : gcc_assert (innerc);
4275 1152 : t1 = OMP_CLAUSE_DECL (innerc);
4276 : }
4277 5318 : if (POINTER_TYPE_P (TREE_TYPE (t0))
4278 2715 : && TYPE_PRECISION (TREE_TYPE (t0))
4279 112 : != TYPE_PRECISION (fd->iter_type))
4280 : {
4281 : /* Avoid casting pointers to integer of a different size. */
4282 0 : tree itype = signed_type_for (type);
4283 0 : t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
4284 0 : t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
4285 : }
4286 : else
4287 : {
4288 2715 : t1 = fold_convert (fd->iter_type, t1);
4289 2715 : t0 = fold_convert (fd->iter_type, t0);
4290 : }
4291 2715 : if (bias)
4292 : {
4293 0 : t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
4294 0 : t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
4295 : }
4296 : }
4297 3050 : if (fd->iter_type == long_integer_type_node || fd->ordered)
4298 : {
4299 2328 : if (fd->chunk_size)
4300 : {
4301 1579 : t = fold_convert (fd->iter_type, fd->chunk_size);
4302 1579 : t = omp_adjust_chunk_size (t, fd->simd_schedule, offload);
4303 1579 : if (sched_arg)
4304 : {
4305 135 : if (fd->ordered)
4306 36 : t = build_call_expr (builtin_decl_explicit (start_fn),
4307 : 8, t0, t1, sched_arg, t, t3, t4,
4308 : reductions, mem);
4309 : else
4310 99 : t = build_call_expr (builtin_decl_explicit (start_fn),
4311 : 9, t0, t1, t2, sched_arg, t, t3, t4,
4312 : reductions, mem);
4313 : }
4314 1444 : else if (fd->ordered)
4315 299 : t = build_call_expr (builtin_decl_explicit (start_fn),
4316 : 5, t0, t1, t, t3, t4);
4317 : else
4318 1145 : t = build_call_expr (builtin_decl_explicit (start_fn),
4319 : 6, t0, t1, t2, t, t3, t4);
4320 : }
4321 749 : else if (fd->ordered)
4322 0 : t = build_call_expr (builtin_decl_explicit (start_fn),
4323 : 4, t0, t1, t3, t4);
4324 : else
4325 749 : t = build_call_expr (builtin_decl_explicit (start_fn),
4326 : 5, t0, t1, t2, t3, t4);
4327 : }
4328 : else
4329 : {
4330 722 : tree t5;
4331 722 : tree c_bool_type;
4332 722 : tree bfn_decl;
4333 :
4334 : /* The GOMP_loop_ull_*start functions have additional boolean
4335 : argument, true for < loops and false for > loops.
4336 : In Fortran, the C bool type can be different from
4337 : boolean_type_node. */
4338 722 : bfn_decl = builtin_decl_explicit (start_fn);
4339 722 : c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
4340 722 : t5 = build_int_cst (c_bool_type,
4341 942 : fd->loop.cond_code == LT_EXPR ? 1 : 0);
4342 722 : if (fd->chunk_size)
4343 : {
4344 390 : tree bfn_decl = builtin_decl_explicit (start_fn);
4345 390 : t = fold_convert (fd->iter_type, fd->chunk_size);
4346 390 : t = omp_adjust_chunk_size (t, fd->simd_schedule, offload);
4347 390 : if (sched_arg)
4348 34 : t = build_call_expr (bfn_decl, 10, t5, t0, t1, t2, sched_arg,
4349 : t, t3, t4, reductions, mem);
4350 : else
4351 356 : t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
4352 : }
4353 : else
4354 332 : t = build_call_expr (builtin_decl_explicit (start_fn),
4355 : 6, t5, t0, t1, t2, t3, t4);
4356 : }
4357 : }
4358 4134 : if (TREE_TYPE (t) != boolean_type_node)
4359 0 : t = fold_build2 (NE_EXPR, boolean_type_node,
4360 : t, build_int_cst (TREE_TYPE (t), 0));
4361 4134 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4362 : true, GSI_SAME_STMT);
4363 4134 : if (arr && !TREE_STATIC (arr))
4364 : {
4365 232 : tree clobber = build_clobber (TREE_TYPE (arr));
4366 232 : gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
4367 : GSI_SAME_STMT);
4368 : }
4369 4134 : if (fd->have_pointer_condtemp)
4370 28 : expand_omp_build_assign (&gsi, condtemp, memv, false);
4371 4134 : if (fd->have_reductemp)
4372 : {
4373 149 : gimple *g = gsi_stmt (gsi);
4374 149 : gsi_remove (&gsi, true);
4375 149 : release_ssa_name (gimple_assign_lhs (g));
4376 :
4377 149 : entry_bb = region->entry;
4378 149 : gsi = gsi_last_nondebug_bb (entry_bb);
4379 :
4380 149 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4381 : }
4382 4134 : gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4383 :
4384 : /* Remove the GIMPLE_OMP_FOR statement. */
4385 4134 : gsi_remove (&gsi, true);
4386 :
4387 4134 : if (gsi_end_p (gsif))
4388 1203 : gsif = gsi_after_labels (gsi_bb (gsif));
4389 4134 : gsi_next (&gsif);
4390 :
4391 : /* Iteration setup for sequential loop goes in L0_BB. */
4392 4134 : tree startvar = fd->loop.v;
4393 4134 : tree endvar = NULL_TREE;
4394 :
4395 4134 : if (gimple_omp_for_combined_p (fd->for_stmt))
4396 : {
4397 1389 : gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
4398 : && gimple_omp_for_kind (inner_stmt)
4399 : == GF_OMP_FOR_KIND_SIMD);
4400 1389 : tree innerc = omp_find_clause (gimple_omp_for_clauses (inner_stmt),
4401 : OMP_CLAUSE__LOOPTEMP_);
4402 1389 : gcc_assert (innerc);
4403 1389 : startvar = OMP_CLAUSE_DECL (innerc);
4404 1389 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
4405 : OMP_CLAUSE__LOOPTEMP_);
4406 1389 : gcc_assert (innerc);
4407 1389 : endvar = OMP_CLAUSE_DECL (innerc);
4408 : }
4409 :
4410 4134 : gsi = gsi_start_bb (l0_bb);
4411 4134 : t = istart0;
4412 4134 : if (fd->ordered && fd->collapse == 1)
4413 188 : t = fold_build2 (MULT_EXPR, fd->iter_type, t,
4414 : fold_convert (fd->iter_type, fd->loop.step));
4415 3946 : else if (bias)
4416 0 : t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
4417 4134 : if (fd->ordered && fd->collapse == 1)
4418 : {
4419 188 : if (POINTER_TYPE_P (TREE_TYPE (startvar)))
4420 8 : t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
4421 : fd->loop.n1, fold_convert (sizetype, t));
4422 : else
4423 : {
4424 180 : t = fold_convert (TREE_TYPE (startvar), t);
4425 180 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
4426 : fd->loop.n1, t);
4427 : }
4428 : }
4429 : else
4430 : {
4431 3946 : if (POINTER_TYPE_P (TREE_TYPE (startvar)))
4432 240 : t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
4433 3946 : t = fold_convert (TREE_TYPE (startvar), t);
4434 : }
4435 4134 : t = force_gimple_operand_gsi (&gsi, t,
4436 4134 : DECL_P (startvar)
4437 4121 : && TREE_ADDRESSABLE (startvar),
4438 : NULL_TREE, false, GSI_CONTINUE_LINKING);
4439 4134 : assign_stmt = gimple_build_assign (startvar, t);
4440 4134 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
4441 4134 : if (cond_var)
4442 : {
4443 46 : tree itype = TREE_TYPE (cond_var);
4444 : /* For lastprivate(conditional:) itervar, we need some iteration
4445 : counter that starts at unsigned non-zero and increases.
4446 : Prefer as few IVs as possible, so if we can use startvar
4447 : itself, use that, or startvar + constant (those would be
4448 : incremented with step), and as last resort use the s0 + 1
4449 : incremented by 1. */
4450 46 : if ((fd->ordered && fd->collapse == 1)
4451 46 : || bias
4452 46 : || POINTER_TYPE_P (type)
4453 46 : || TREE_CODE (fd->loop.n1) != INTEGER_CST
4454 40 : || fd->loop.cond_code != LT_EXPR)
4455 6 : t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, istart0),
4456 : build_int_cst (itype, 1));
4457 40 : else if (tree_int_cst_sgn (fd->loop.n1) == 1)
4458 9 : t = fold_convert (itype, t);
4459 : else
4460 : {
4461 31 : tree c = fold_convert (itype, fd->loop.n1);
4462 31 : c = fold_build2 (MINUS_EXPR, itype, build_int_cst (itype, 1), c);
4463 31 : t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, t), c);
4464 : }
4465 46 : t = force_gimple_operand_gsi (&gsi, t, false,
4466 : NULL_TREE, false, GSI_CONTINUE_LINKING);
4467 46 : assign_stmt = gimple_build_assign (cond_var, t);
4468 46 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
4469 : }
4470 :
4471 4134 : t = iend0;
4472 4134 : if (fd->ordered && fd->collapse == 1)
4473 188 : t = fold_build2 (MULT_EXPR, fd->iter_type, t,
4474 : fold_convert (fd->iter_type, fd->loop.step));
4475 3946 : else if (bias)
4476 0 : t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
4477 4134 : if (fd->ordered && fd->collapse == 1)
4478 : {
4479 188 : if (POINTER_TYPE_P (TREE_TYPE (startvar)))
4480 8 : t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
4481 : fd->loop.n1, fold_convert (sizetype, t));
4482 : else
4483 : {
4484 180 : t = fold_convert (TREE_TYPE (startvar), t);
4485 180 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
4486 : fd->loop.n1, t);
4487 : }
4488 : }
4489 : else
4490 : {
4491 3946 : if (POINTER_TYPE_P (TREE_TYPE (startvar)))
4492 240 : t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
4493 3946 : t = fold_convert (TREE_TYPE (startvar), t);
4494 : }
4495 4134 : iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4496 : false, GSI_CONTINUE_LINKING);
4497 4134 : if (endvar)
4498 : {
4499 1389 : assign_stmt = gimple_build_assign (endvar, iend);
4500 1389 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
4501 1389 : if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
4502 857 : assign_stmt = gimple_build_assign (fd->loop.v, iend);
4503 : else
4504 532 : assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
4505 1389 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
4506 : }
4507 : /* Handle linear clause adjustments. */
4508 4134 : tree itercnt = NULL_TREE;
4509 4134 : if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
4510 27021 : for (tree c = gimple_omp_for_clauses (fd->for_stmt);
4511 27021 : c; c = OMP_CLAUSE_CHAIN (c))
4512 22887 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4513 22887 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4514 : {
4515 72 : tree d = OMP_CLAUSE_DECL (c);
4516 72 : tree t = d, a, dest;
4517 72 : if (omp_privatize_by_reference (t))
4518 2 : t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
4519 72 : tree type = TREE_TYPE (t);
4520 72 : if (POINTER_TYPE_P (type))
4521 0 : type = sizetype;
4522 72 : dest = unshare_expr (t);
4523 72 : tree v = create_tmp_var (TREE_TYPE (t), NULL);
4524 72 : expand_omp_build_assign (&gsif, v, t);
4525 72 : if (itercnt == NULL_TREE)
4526 : {
4527 72 : itercnt = startvar;
4528 72 : tree n1 = fd->loop.n1;
4529 72 : if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
4530 : {
4531 0 : itercnt
4532 0 : = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
4533 : itercnt);
4534 0 : n1 = fold_convert (TREE_TYPE (itercnt), n1);
4535 : }
4536 72 : itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
4537 : itercnt, n1);
4538 72 : itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
4539 : itercnt, fd->loop.step);
4540 72 : itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
4541 : NULL_TREE, false,
4542 : GSI_CONTINUE_LINKING);
4543 : }
4544 72 : a = fold_build2 (MULT_EXPR, type,
4545 : fold_convert (type, itercnt),
4546 : fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
4547 72 : t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
4548 : : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
4549 72 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4550 : false, GSI_CONTINUE_LINKING);
4551 72 : expand_omp_build_assign (&gsi, dest, t, true);
4552 : }
4553 4134 : if (fd->collapse > 1)
4554 1481 : expand_omp_for_init_vars (fd, &gsi, counts, NULL, inner_stmt, startvar);
4555 :
4556 4134 : if (fd->ordered)
4557 : {
4558 : /* Until now, counts array contained number of iterations or
4559 : variable containing it for ith loop. From now on, we usually need
4560 : those counts only for collapsed loops, and only for the 2nd
4561 : till the last collapsed one. Move those one element earlier,
4562 : we'll use counts[fd->collapse - 1] for the first source/sink
4563 : iteration counter and so on and counts[fd->ordered]
4564 : as the array holding the current counter values for
4565 : depend(source). For doacross(sink:omp_cur_iteration - 1) we need
4566 : the counts from fd->collapse to fd->ordered - 1; make a copy of
4567 : those to counts[fd->ordered + 2] and onwards.
4568 : counts[fd->ordered + 1] can be a flag whether it is the first
4569 : iteration with a new collapsed counter (used only if
4570 : fd->ordered > fd->collapse). */
4571 335 : if (fd->ordered > fd->collapse)
4572 171 : memcpy (counts + fd->ordered + 2, counts + fd->collapse,
4573 171 : (fd->ordered - fd->collapse) * sizeof (counts[0]));
4574 335 : if (fd->collapse > 1)
4575 147 : memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
4576 335 : if (broken_loop)
4577 : {
4578 : int i;
4579 41 : for (i = fd->collapse; i < fd->ordered; i++)
4580 : {
4581 33 : tree type = TREE_TYPE (fd->loops[i].v);
4582 33 : tree this_cond
4583 33 : = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
4584 : fold_convert (type, fd->loops[i].n1),
4585 : fold_convert (type, fd->loops[i].n2));
4586 33 : if (!integer_onep (this_cond))
4587 : break;
4588 : }
4589 37 : if (i < fd->ordered)
4590 : {
4591 29 : if (entry_bb->loop_father != l0_bb->loop_father)
4592 : {
4593 4 : remove_bb_from_loops (l0_bb);
4594 4 : add_bb_to_loop (l0_bb, entry_bb->loop_father);
4595 4 : gcc_assert (single_succ (l0_bb) == l1_bb);
4596 : }
4597 29 : cont_bb
4598 29 : = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
4599 29 : add_bb_to_loop (cont_bb, l0_bb->loop_father);
4600 29 : gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
4601 29 : gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
4602 29 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
4603 29 : make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
4604 29 : make_edge (cont_bb, l1_bb, 0);
4605 29 : l2_bb = create_empty_bb (cont_bb);
4606 29 : broken_loop = false;
4607 : }
4608 : }
4609 335 : expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
4610 335 : cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
4611 : l0_bb, ordered_lastprivate);
4612 335 : if (counts[fd->collapse - 1])
4613 : {
4614 37 : gcc_assert (fd->collapse == 1);
4615 37 : gsi = gsi_last_bb (l0_bb);
4616 37 : expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
4617 : istart0, true);
4618 37 : if (cont_bb)
4619 : {
4620 33 : gsi = gsi_last_bb (cont_bb);
4621 33 : t = fold_build2 (PLUS_EXPR, fd->iter_type,
4622 : counts[fd->collapse - 1],
4623 : build_int_cst (fd->iter_type, 1));
4624 33 : expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
4625 66 : tree aref = build4 (ARRAY_REF, fd->iter_type,
4626 33 : counts[fd->ordered], size_zero_node,
4627 : NULL_TREE, NULL_TREE);
4628 33 : expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
4629 : }
4630 37 : t = counts[fd->collapse - 1];
4631 : }
4632 298 : else if (fd->collapse > 1)
4633 147 : t = fd->loop.v;
4634 : else
4635 : {
4636 151 : t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
4637 : fd->loops[0].v, fd->loops[0].n1);
4638 151 : t = fold_convert (fd->iter_type, t);
4639 : }
4640 335 : gsi = gsi_last_bb (l0_bb);
4641 335 : tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
4642 : size_zero_node, NULL_TREE, NULL_TREE);
4643 335 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4644 : false, GSI_CONTINUE_LINKING);
4645 335 : expand_omp_build_assign (&gsi, aref, t, true);
4646 : }
4647 :
4648 4134 : if (!broken_loop)
4649 : {
4650 : /* Code to control the increment and predicate for the sequential
4651 : loop goes in the CONT_BB. */
4652 3756 : gsi = gsi_last_nondebug_bb (cont_bb);
4653 3756 : gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
4654 3756 : gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
4655 3756 : vmain = gimple_omp_continue_control_use (cont_stmt);
4656 3756 : vback = gimple_omp_continue_control_def (cont_stmt);
4657 :
4658 3756 : if (cond_var)
4659 : {
4660 46 : tree itype = TREE_TYPE (cond_var);
4661 46 : tree t2;
4662 46 : if ((fd->ordered && fd->collapse == 1)
4663 46 : || bias
4664 46 : || POINTER_TYPE_P (type)
4665 46 : || TREE_CODE (fd->loop.n1) != INTEGER_CST
4666 40 : || fd->loop.cond_code != LT_EXPR)
4667 6 : t2 = build_int_cst (itype, 1);
4668 : else
4669 40 : t2 = fold_convert (itype, fd->loop.step);
4670 46 : t2 = fold_build2 (PLUS_EXPR, itype, cond_var, t2);
4671 46 : t2 = force_gimple_operand_gsi (&gsi, t2, false,
4672 : NULL_TREE, true, GSI_SAME_STMT);
4673 46 : assign_stmt = gimple_build_assign (cond_var, t2);
4674 46 : gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
4675 : }
4676 :
4677 3756 : if (!gimple_omp_for_combined_p (fd->for_stmt))
4678 : {
4679 2367 : if (POINTER_TYPE_P (type))
4680 160 : t = fold_build_pointer_plus (vmain, fd->loop.step);
4681 : else
4682 2207 : t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
4683 2367 : t = force_gimple_operand_gsi (&gsi, t,
4684 2367 : DECL_P (vback)
4685 2354 : && TREE_ADDRESSABLE (vback),
4686 : NULL_TREE, true, GSI_SAME_STMT);
4687 2367 : assign_stmt = gimple_build_assign (vback, t);
4688 2367 : gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
4689 :
4690 2367 : if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
4691 : {
4692 294 : tree tem;
4693 294 : if (fd->collapse > 1)
4694 143 : tem = fd->loop.v;
4695 : else
4696 : {
4697 151 : tem = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
4698 : fd->loops[0].v, fd->loops[0].n1);
4699 151 : tem = fold_convert (fd->iter_type, tem);
4700 : }
4701 588 : tree aref = build4 (ARRAY_REF, fd->iter_type,
4702 294 : counts[fd->ordered], size_zero_node,
4703 : NULL_TREE, NULL_TREE);
4704 294 : tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE,
4705 : true, GSI_SAME_STMT);
4706 294 : expand_omp_build_assign (&gsi, aref, tem);
4707 : }
4708 :
4709 2367 : t = build2 (fd->loop.cond_code, boolean_type_node,
4710 2367 : DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
4711 : iend);
4712 2367 : gcond *cond_stmt = gimple_build_cond_empty (t);
4713 2367 : gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
4714 : }
4715 :
4716 : /* Remove GIMPLE_OMP_CONTINUE. */
4717 3756 : gsi_remove (&gsi, true);
4718 :
4719 3756 : if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
4720 681 : collapse_bb = extract_omp_for_update_vars (fd, NULL, cont_bb, l1_bb);
4721 :
4722 : /* Emit code to get the next parallel iteration in L2_BB. */
4723 3756 : gsi = gsi_start_bb (l2_bb);
4724 :
4725 3756 : t = build_call_expr (builtin_decl_explicit (next_fn), 2,
4726 : build_fold_addr_expr (istart0),
4727 : build_fold_addr_expr (iend0));
4728 3756 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4729 : false, GSI_CONTINUE_LINKING);
4730 3756 : if (TREE_TYPE (t) != boolean_type_node)
4731 0 : t = fold_build2 (NE_EXPR, boolean_type_node,
4732 : t, build_int_cst (TREE_TYPE (t), 0));
4733 3756 : gcond *cond_stmt = gimple_build_cond_empty (t);
4734 3756 : gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
4735 : }
4736 :
4737 : /* Add the loop cleanup function. */
4738 4134 : gsi = gsi_last_nondebug_bb (exit_bb);
4739 4134 : if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4740 3047 : t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
4741 1087 : else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
4742 2 : t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
4743 : else
4744 1085 : t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
4745 4134 : gcall *call_stmt = gimple_build_call (t, 0);
4746 4134 : if (fd->ordered)
4747 : {
4748 335 : tree arr = counts[fd->ordered];
4749 335 : tree clobber = build_clobber (TREE_TYPE (arr));
4750 335 : gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
4751 : GSI_SAME_STMT);
4752 : }
4753 4134 : if (gimple_omp_return_lhs (gsi_stmt (gsi)))
4754 : {
4755 2 : gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
4756 2 : if (fd->have_reductemp)
4757 : {
4758 0 : gimple *g = gimple_build_assign (reductions, NOP_EXPR,
4759 : gimple_call_lhs (call_stmt));
4760 0 : gsi_insert_after (&gsi, g, GSI_SAME_STMT);
4761 : }
4762 : }
4763 4134 : gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
4764 4134 : gsi_remove (&gsi, true);
4765 :
4766 : /* Connect the new blocks. */
4767 4134 : find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
4768 4134 : find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
4769 :
4770 4134 : if (!broken_loop)
4771 : {
4772 3756 : gimple_seq phis;
4773 :
4774 3756 : e = find_edge (cont_bb, l3_bb);
4775 3756 : ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
4776 :
4777 3756 : phis = phi_nodes (l3_bb);
4778 3778 : for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
4779 : {
4780 11 : gimple *phi = gsi_stmt (gsi);
4781 11 : SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
4782 : PHI_ARG_DEF_FROM_EDGE (phi, e));
4783 : }
4784 3756 : remove_edge (e);
4785 :
4786 3756 : make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
4787 3756 : e = find_edge (cont_bb, l1_bb);
4788 3756 : if (e == NULL)
4789 : {
4790 13 : e = BRANCH_EDGE (cont_bb);
4791 13 : gcc_assert (single_succ (e->dest) == l1_bb);
4792 : }
4793 3756 : if (gimple_omp_for_combined_p (fd->for_stmt))
4794 : {
4795 1389 : remove_edge (e);
4796 1389 : e = NULL;
4797 : }
4798 2367 : else if (fd->collapse > 1)
4799 : {
4800 681 : remove_edge (e);
4801 681 : e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
4802 : }
4803 : else
4804 1686 : e->flags = EDGE_TRUE_VALUE;
4805 3756 : if (e)
4806 : {
4807 2367 : e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
4808 2367 : find_edge (cont_bb, l2_bb)->probability = e->probability.invert ();
4809 : }
4810 : else
4811 : {
4812 1389 : e = find_edge (cont_bb, l2_bb);
4813 1389 : e->flags = EDGE_FALLTHRU;
4814 : }
4815 3756 : make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
4816 :
4817 3756 : if (gimple_in_ssa_p (cfun))
4818 : {
4819 : /* Add phis to the outer loop that connect to the phis in the inner,
4820 : original loop, and move the loop entry value of the inner phi to
4821 : the loop entry value of the outer phi. */
4822 13 : gphi_iterator psi;
4823 24 : for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
4824 : {
4825 11 : location_t locus;
4826 11 : gphi *nphi;
4827 11 : gphi *exit_phi = psi.phi ();
4828 :
4829 22 : if (virtual_operand_p (gimple_phi_result (exit_phi)))
4830 6 : continue;
4831 :
4832 5 : edge l2_to_l3 = find_edge (l2_bb, l3_bb);
4833 5 : tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
4834 :
4835 5 : basic_block latch = BRANCH_EDGE (cont_bb)->dest;
4836 5 : edge latch_to_l1 = find_edge (latch, l1_bb);
4837 5 : gphi *inner_phi
4838 5 : = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
4839 :
4840 5 : tree t = gimple_phi_result (exit_phi);
4841 5 : tree new_res = copy_ssa_name (t, NULL);
4842 5 : nphi = create_phi_node (new_res, l0_bb);
4843 :
4844 5 : edge l0_to_l1 = find_edge (l0_bb, l1_bb);
4845 5 : t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
4846 5 : locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
4847 5 : edge entry_to_l0 = find_edge (entry_bb, l0_bb);
4848 5 : add_phi_arg (nphi, t, entry_to_l0, locus);
4849 :
4850 5 : edge l2_to_l0 = find_edge (l2_bb, l0_bb);
4851 5 : add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
4852 :
4853 5 : add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
4854 : }
4855 : }
4856 :
4857 3756 : set_immediate_dominator (CDI_DOMINATORS, l2_bb,
4858 : recompute_dominator (CDI_DOMINATORS, l2_bb));
4859 3756 : set_immediate_dominator (CDI_DOMINATORS, l3_bb,
4860 : recompute_dominator (CDI_DOMINATORS, l3_bb));
4861 3756 : set_immediate_dominator (CDI_DOMINATORS, l0_bb,
4862 : recompute_dominator (CDI_DOMINATORS, l0_bb));
4863 3756 : set_immediate_dominator (CDI_DOMINATORS, l1_bb,
4864 : recompute_dominator (CDI_DOMINATORS, l1_bb));
4865 :
4866 : /* We enter expand_omp_for_generic with a loop. This original loop may
4867 : have its own loop struct, or it may be part of an outer loop struct
4868 : (which may be the fake loop). */
4869 3756 : class loop *outer_loop = entry_bb->loop_father;
4870 3756 : bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
4871 :
4872 3756 : add_bb_to_loop (l2_bb, outer_loop);
4873 :
4874 : /* We've added a new loop around the original loop. Allocate the
4875 : corresponding loop struct. */
4876 3756 : class loop *new_loop = alloc_loop ();
4877 3756 : new_loop->header = l0_bb;
4878 3756 : new_loop->latch = l2_bb;
4879 3756 : add_loop (new_loop, outer_loop);
4880 :
4881 : /* Allocate a loop structure for the original loop unless we already
4882 : had one. */
4883 3756 : if (!orig_loop_has_loop_struct
4884 3756 : && !gimple_omp_for_combined_p (fd->for_stmt))
4885 : {
4886 2350 : class loop *orig_loop = alloc_loop ();
4887 2350 : orig_loop->header = l1_bb;
4888 : /* The loop may have multiple latches. */
4889 2350 : add_loop (orig_loop, new_loop);
4890 : }
4891 : }
4892 4134 : }
4893 :
4894 : /* Helper function for expand_omp_for_static_nochunk. If PTR is NULL,
4895 : compute needed allocation size. If !ALLOC of team allocations,
4896 : if ALLOC of thread allocation. SZ is the initial needed size for
4897 : other purposes, ALLOC_ALIGN guaranteed alignment of allocation in bytes,
4898 : CNT number of elements of each array, for !ALLOC this is
4899 : omp_get_num_threads (), for ALLOC number of iterations handled by the
4900 : current thread. If PTR is non-NULL, it is the start of the allocation
4901 : and this routine shall assign to OMP_CLAUSE_DECL (c) of those _scantemp_
4902 : clauses pointers to the corresponding arrays. */
4903 :
4904 : static tree
4905 740 : expand_omp_scantemp_alloc (tree clauses, tree ptr, unsigned HOST_WIDE_INT sz,
4906 : unsigned HOST_WIDE_INT alloc_align, tree cnt,
4907 : gimple_stmt_iterator *gsi, bool alloc)
4908 : {
4909 740 : tree eltsz = NULL_TREE;
4910 740 : unsigned HOST_WIDE_INT preval = 0;
4911 740 : if (ptr && sz)
4912 5 : ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr),
4913 : ptr, size_int (sz));
4914 6088 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
4915 5348 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__SCANTEMP_
4916 3216 : && !OMP_CLAUSE__SCANTEMP__CONTROL (c)
4917 7084 : && (!OMP_CLAUSE__SCANTEMP__ALLOC (c)) != alloc)
4918 : {
4919 868 : tree pointee_type = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
4920 868 : unsigned HOST_WIDE_INT al = TYPE_ALIGN_UNIT (pointee_type);
4921 868 : if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (pointee_type)))
4922 : {
4923 868 : unsigned HOST_WIDE_INT szl
4924 868 : = tree_to_uhwi (TYPE_SIZE_UNIT (pointee_type));
4925 868 : szl = least_bit_hwi (szl);
4926 868 : if (szl)
4927 868 : al = MIN (al, szl);
4928 : }
4929 868 : if (ptr == NULL_TREE)
4930 : {
4931 434 : if (eltsz == NULL_TREE)
4932 370 : eltsz = TYPE_SIZE_UNIT (pointee_type);
4933 : else
4934 64 : eltsz = size_binop (PLUS_EXPR, eltsz,
4935 : TYPE_SIZE_UNIT (pointee_type));
4936 : }
4937 868 : if (preval == 0 && al <= alloc_align)
4938 : {
4939 740 : unsigned HOST_WIDE_INT diff = ROUND_UP (sz, al) - sz;
4940 740 : sz += diff;
4941 740 : if (diff && ptr)
4942 0 : ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr),
4943 : ptr, size_int (diff));
4944 : }
4945 128 : else if (al > preval)
4946 : {
4947 32 : if (ptr)
4948 : {
4949 16 : ptr = fold_convert (pointer_sized_int_node, ptr);
4950 16 : ptr = fold_build2 (PLUS_EXPR, pointer_sized_int_node, ptr,
4951 : build_int_cst (pointer_sized_int_node,
4952 : al - 1));
4953 16 : ptr = fold_build2 (BIT_AND_EXPR, pointer_sized_int_node, ptr,
4954 : build_int_cst (pointer_sized_int_node,
4955 : -(HOST_WIDE_INT) al));
4956 16 : ptr = fold_convert (ptr_type_node, ptr);
4957 : }
4958 : else
4959 16 : sz += al - 1;
4960 : }
4961 868 : if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (pointee_type)))
4962 : preval = al;
4963 : else
4964 0 : preval = 1;
4965 868 : if (ptr)
4966 : {
4967 434 : expand_omp_build_assign (gsi, OMP_CLAUSE_DECL (c), ptr, false);
4968 434 : ptr = OMP_CLAUSE_DECL (c);
4969 434 : ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr,
4970 : size_binop (MULT_EXPR, cnt,
4971 : TYPE_SIZE_UNIT (pointee_type)));
4972 : }
4973 : }
4974 :
4975 740 : if (ptr == NULL_TREE)
4976 : {
4977 370 : eltsz = size_binop (MULT_EXPR, eltsz, cnt);
4978 370 : if (sz)
4979 13 : eltsz = size_binop (PLUS_EXPR, eltsz, size_int (sz));
4980 : return eltsz;
4981 : }
4982 : else
4983 : return ptr;
4984 : }
4985 :
4986 : /* Return the last _looptemp_ clause if one has been created for
4987 : lastprivate on distribute parallel for{, simd} or taskloop.
4988 : FD is the loop data and INNERC should be the second _looptemp_
4989 : clause (the one holding the end of the range).
4990 : This is followed by collapse - 1 _looptemp_ clauses for the
4991 : counts[1] and up, and for triangular loops followed by 4
4992 : further _looptemp_ clauses (one for counts[0], one first_inner_iterations,
4993 : one factor and one adjn1). After this there is optionally one
4994 : _looptemp_ clause that this function returns. */
4995 :
4996 : static tree
4997 1634 : find_lastprivate_looptemp (struct omp_for_data *fd, tree innerc)
4998 : {
4999 1634 : gcc_assert (innerc);
5000 1634 : int count = fd->collapse - 1;
5001 1634 : if (fd->non_rect
5002 24 : && fd->last_nonrect == fd->first_nonrect + 1
5003 1646 : && !TYPE_UNSIGNED (TREE_TYPE (fd->loops[fd->last_nonrect].v)))
5004 12 : count += 4;
5005 4811 : for (int i = 0; i < count; i++)
5006 : {
5007 3177 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
5008 : OMP_CLAUSE__LOOPTEMP_);
5009 3177 : gcc_assert (innerc);
5010 : }
5011 1634 : return omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
5012 1634 : OMP_CLAUSE__LOOPTEMP_);
5013 : }
5014 :
5015 : /* A subroutine of expand_omp_for. Generate code for a parallel
5016 : loop with static schedule and no specified chunk size. Given
5017 : parameters:
5018 :
5019 : for (V = N1; V cond N2; V += STEP) BODY;
5020 :
5021 : where COND is "<" or ">", we generate pseudocode
5022 :
5023 : if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5024 : if (cond is <)
5025 : adj = STEP - 1;
5026 : else
5027 : adj = STEP + 1;
5028 : if ((__typeof (V)) -1 > 0 && cond is >)
5029 : n = -(adj + N2 - N1) / -STEP;
5030 : else
5031 : n = (adj + N2 - N1) / STEP;
5032 : q = n / nthreads;
5033 : tt = n % nthreads;
5034 : if (threadid < tt) goto L3; else goto L4;
5035 : L3:
5036 : tt = 0;
5037 : q = q + 1;
5038 : L4:
5039 : s0 = q * threadid + tt;
5040 : e0 = s0 + q;
5041 : V = s0 * STEP + N1;
5042 : if (s0 >= e0) goto L2; else goto L0;
5043 : L0:
5044 : e = e0 * STEP + N1;
5045 : L1:
5046 : BODY;
5047 : V += STEP;
5048 : if (V cond e) goto L1;
5049 : L2:
5050 : */
5051 :
5052 : static void
5053 14067 : expand_omp_for_static_nochunk (struct omp_region *region,
5054 : struct omp_for_data *fd,
5055 : gimple *inner_stmt)
5056 : {
5057 14067 : tree n, q, s0, e0, e, t, tt, nthreads = NULL_TREE, threadid;
5058 14067 : tree type, itype, vmain, vback;
5059 14067 : basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5060 14067 : basic_block body_bb, cont_bb, collapse_bb = NULL;
5061 14067 : basic_block fin_bb, fourth_bb = NULL, fifth_bb = NULL, sixth_bb = NULL;
5062 14067 : basic_block exit1_bb = NULL, exit2_bb = NULL, exit3_bb = NULL;
5063 14067 : gimple_stmt_iterator gsi, gsip;
5064 14067 : edge ep;
5065 14067 : bool broken_loop = region->cont == NULL;
5066 14067 : tree *counts = NULL;
5067 14067 : tree n1, n2, step;
5068 14067 : tree reductions = NULL_TREE;
5069 14067 : tree cond_var = NULL_TREE, condtemp = NULL_TREE;
5070 :
5071 14067 : itype = type = TREE_TYPE (fd->loop.v);
5072 14067 : if (POINTER_TYPE_P (type))
5073 606 : itype = signed_type_for (type);
5074 :
5075 14067 : entry_bb = region->entry;
5076 14067 : cont_bb = region->cont;
5077 14067 : gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5078 14067 : fin_bb = BRANCH_EDGE (entry_bb)->dest;
5079 14067 : gcc_assert (broken_loop
5080 : || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5081 14067 : seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5082 14067 : body_bb = single_succ (seq_start_bb);
5083 14067 : if (!broken_loop)
5084 : {
5085 13571 : gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
5086 : || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
5087 13571 : gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5088 : }
5089 14067 : exit_bb = region->exit;
5090 :
5091 : /* Iteration space partitioning goes in ENTRY_BB. */
5092 14067 : gsi = gsi_last_nondebug_bb (entry_bb);
5093 14067 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5094 14067 : gsip = gsi;
5095 14067 : gsi_prev (&gsip);
5096 :
5097 14067 : if (fd->collapse > 1)
5098 : {
5099 3921 : int first_zero_iter = -1, dummy = -1;
5100 3921 : basic_block l2_dom_bb = NULL, dummy_bb = NULL;
5101 :
5102 3921 : counts = XALLOCAVEC (tree, fd->collapse);
5103 3921 : expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5104 : fin_bb, first_zero_iter,
5105 : dummy_bb, dummy, l2_dom_bb);
5106 3921 : t = NULL_TREE;
5107 : }
5108 10146 : else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5109 2031 : t = integer_one_node;
5110 : else
5111 8115 : t = fold_binary (fd->loop.cond_code, boolean_type_node,
5112 : fold_convert (type, fd->loop.n1),
5113 : fold_convert (type, fd->loop.n2));
5114 14067 : if (fd->collapse == 1
5115 10146 : && TYPE_UNSIGNED (type)
5116 16080 : && (t == NULL_TREE || !integer_onep (t)))
5117 : {
5118 523 : n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5119 523 : n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5120 : true, GSI_SAME_STMT);
5121 523 : n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5122 523 : n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5123 : true, GSI_SAME_STMT);
5124 523 : gcond *cond_stmt = expand_omp_build_cond (&gsi, fd->loop.cond_code,
5125 : n1, n2);
5126 523 : ep = split_block (entry_bb, cond_stmt);
5127 523 : ep->flags = EDGE_TRUE_VALUE;
5128 523 : entry_bb = ep->dest;
5129 523 : ep->probability = profile_probability::very_likely ();
5130 523 : ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5131 523 : ep->probability = profile_probability::very_unlikely ();
5132 523 : if (gimple_in_ssa_p (cfun))
5133 : {
5134 22 : int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5135 22 : for (gphi_iterator gpi = gsi_start_phis (fin_bb);
5136 44 : !gsi_end_p (gpi); gsi_next (&gpi))
5137 : {
5138 22 : gphi *phi = gpi.phi ();
5139 22 : add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5140 : ep, UNKNOWN_LOCATION);
5141 : }
5142 : }
5143 1046 : gsi = gsi_last_bb (entry_bb);
5144 : }
5145 :
5146 14067 : if (fd->lastprivate_conditional)
5147 : {
5148 108 : tree clauses = gimple_omp_for_clauses (fd->for_stmt);
5149 108 : tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
5150 108 : if (fd->have_pointer_condtemp)
5151 38 : condtemp = OMP_CLAUSE_DECL (c);
5152 108 : c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE__CONDTEMP_);
5153 108 : cond_var = OMP_CLAUSE_DECL (c);
5154 : }
5155 14067 : if (fd->have_reductemp
5156 : /* For scan, we don't want to reinitialize condtemp before the
5157 : second loop. */
5158 14014 : || (fd->have_pointer_condtemp && !fd->have_scantemp)
5159 13996 : || fd->have_nonctrl_scantemp)
5160 : {
5161 256 : tree t1 = build_int_cst (long_integer_type_node, 0);
5162 256 : tree t2 = build_int_cst (long_integer_type_node, 1);
5163 256 : tree t3 = build_int_cstu (long_integer_type_node,
5164 : (HOST_WIDE_INT_1U << 31) + 1);
5165 256 : tree clauses = gimple_omp_for_clauses (fd->for_stmt);
5166 256 : gimple_stmt_iterator gsi2 = gsi_none ();
5167 256 : gimple *g = NULL;
5168 256 : tree mem = null_pointer_node, memv = NULL_TREE;
5169 256 : unsigned HOST_WIDE_INT condtemp_sz = 0;
5170 256 : unsigned HOST_WIDE_INT alloc_align = 0;
5171 256 : if (fd->have_reductemp)
5172 : {
5173 53 : gcc_assert (!fd->have_nonctrl_scantemp);
5174 53 : tree c = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
5175 53 : reductions = OMP_CLAUSE_DECL (c);
5176 53 : gcc_assert (TREE_CODE (reductions) == SSA_NAME);
5177 53 : g = SSA_NAME_DEF_STMT (reductions);
5178 53 : reductions = gimple_assign_rhs1 (g);
5179 53 : OMP_CLAUSE_DECL (c) = reductions;
5180 53 : gsi2 = gsi_for_stmt (g);
5181 : }
5182 : else
5183 : {
5184 203 : if (gsi_end_p (gsip))
5185 0 : gsi2 = gsi_after_labels (region->entry);
5186 : else
5187 203 : gsi2 = gsip;
5188 : reductions = null_pointer_node;
5189 : }
5190 256 : if (fd->have_pointer_condtemp || fd->have_nonctrl_scantemp)
5191 : {
5192 213 : tree type;
5193 213 : if (fd->have_pointer_condtemp)
5194 33 : type = TREE_TYPE (condtemp);
5195 : else
5196 180 : type = ptr_type_node;
5197 213 : memv = create_tmp_var (type);
5198 213 : TREE_ADDRESSABLE (memv) = 1;
5199 213 : unsigned HOST_WIDE_INT sz = 0;
5200 213 : tree size = NULL_TREE;
5201 213 : if (fd->have_pointer_condtemp)
5202 : {
5203 33 : sz = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
5204 33 : sz *= fd->lastprivate_conditional;
5205 33 : condtemp_sz = sz;
5206 : }
5207 213 : if (fd->have_nonctrl_scantemp)
5208 : {
5209 185 : nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5210 185 : gimple *g = gimple_build_call (nthreads, 0);
5211 185 : nthreads = create_tmp_var (integer_type_node);
5212 185 : gimple_call_set_lhs (g, nthreads);
5213 185 : gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
5214 185 : nthreads = fold_convert (sizetype, nthreads);
5215 185 : alloc_align = TYPE_ALIGN_UNIT (long_long_integer_type_node);
5216 185 : size = expand_omp_scantemp_alloc (clauses, NULL_TREE, sz,
5217 : alloc_align, nthreads, NULL,
5218 : false);
5219 185 : size = fold_convert (type, size);
5220 : }
5221 : else
5222 28 : size = build_int_cst (type, sz);
5223 213 : expand_omp_build_assign (&gsi2, memv, size, false);
5224 213 : mem = build_fold_addr_expr (memv);
5225 : }
5226 256 : tree t
5227 256 : = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_LOOP_START),
5228 : 9, t1, t2, t2, t3, t1, null_pointer_node,
5229 : null_pointer_node, reductions, mem);
5230 256 : force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
5231 : true, GSI_SAME_STMT);
5232 256 : if (fd->have_pointer_condtemp)
5233 33 : expand_omp_build_assign (&gsi2, condtemp, memv, false);
5234 256 : if (fd->have_nonctrl_scantemp)
5235 : {
5236 185 : tree ptr = fd->have_pointer_condtemp ? condtemp : memv;
5237 185 : expand_omp_scantemp_alloc (clauses, ptr, condtemp_sz,
5238 : alloc_align, nthreads, &gsi2, false);
5239 : }
5240 256 : if (fd->have_reductemp)
5241 : {
5242 53 : gsi_remove (&gsi2, true);
5243 53 : release_ssa_name (gimple_assign_lhs (g));
5244 : }
5245 : }
5246 :
5247 14067 : n1 = fd->loop.n1;
5248 14067 : n2 = fd->loop.n2;
5249 14067 : step = fd->loop.step;
5250 14067 : if (gimple_omp_for_combined_into_p (fd->for_stmt))
5251 : {
5252 3075 : tree innerc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
5253 : OMP_CLAUSE__LOOPTEMP_);
5254 3075 : gcc_assert (innerc);
5255 3075 : n1 = OMP_CLAUSE_DECL (innerc);
5256 3075 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
5257 : OMP_CLAUSE__LOOPTEMP_);
5258 3075 : gcc_assert (innerc);
5259 3075 : n2 = OMP_CLAUSE_DECL (innerc);
5260 : }
5261 14067 : n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5262 : true, NULL_TREE, true, GSI_SAME_STMT);
5263 14067 : n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5264 : true, NULL_TREE, true, GSI_SAME_STMT);
5265 14067 : step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5266 : true, NULL_TREE, true, GSI_SAME_STMT);
5267 :
5268 15086 : t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5269 14067 : t = fold_build2 (PLUS_EXPR, itype, step, t);
5270 14067 : t = fold_build2 (PLUS_EXPR, itype, t, n2);
5271 14067 : t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5272 14067 : if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5273 414 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
5274 : fold_build1 (NEGATE_EXPR, itype, t),
5275 : fold_build1 (NEGATE_EXPR, itype, step));
5276 : else
5277 13653 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5278 14067 : t = fold_convert (itype, t);
5279 14067 : n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5280 :
5281 : /* When GOMP_loop_end (or one of its variants) is emitted (e.g. with the
5282 : inscan modifier), which already implies the end of the scope, _start
5283 : variants of GOMP builtin calls have to be used and _end can be skipped. */
5284 28134 : bool has_gomp_loop_end = fd->have_reductemp
5285 14067 : || ((fd->have_pointer_condtemp || fd->have_scantemp)
5286 388 : && !fd->have_nonctrl_scantemp);
5287 14067 : {
5288 : /* Fetch the thread/team id and the number of threads/teams in a single
5289 : call to GOMP_loop_static_worksharing or
5290 : GOMP_distribute_static_worksharing. The helper returns both values packed
5291 : into one complex int, with the id as the imaginary part and the count as
5292 : the real part. Returning (rather than writing through pointers) keeps
5293 : both values as plain SSA names, which lets later passes - notably IPA-CP
5294 : propagating constants into the outlined kernel - reason about them.
5295 : Also pass the total number of iterations for OMPT. */
5296 14067 : tree decl;
5297 14067 : switch (gimple_omp_for_kind (fd->for_stmt))
5298 : {
5299 9494 : case GF_OMP_FOR_KIND_FOR:
5300 18988 : decl = builtin_decl_explicit (
5301 9494 : flag_openmp_ompt || has_gomp_loop_end
5302 : ? BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_START
5303 : : BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING);
5304 9494 : break;
5305 4573 : case GF_OMP_FOR_KIND_DISTRIBUTE:
5306 9146 : decl = builtin_decl_explicit (
5307 4573 : flag_openmp_ompt || has_gomp_loop_end
5308 : ? BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_START
5309 : : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING);
5310 4573 : break;
5311 0 : default:
5312 0 : gcc_unreachable ();
5313 : }
5314 14067 : tree n_ull = fold_convert (long_long_unsigned_type_node, n);
5315 14067 : tree packed = build_call_expr (decl, 1, n_ull);
5316 14067 : packed = force_gimple_operand_gsi (&gsi, packed, true, NULL_TREE,
5317 : true, GSI_SAME_STMT);
5318 14067 : threadid = fold_build1 (IMAGPART_EXPR, integer_type_node, packed);
5319 14067 : threadid = fold_convert (itype, threadid);
5320 14067 : threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
5321 : true, GSI_SAME_STMT);
5322 14067 : nthreads = fold_build1 (REALPART_EXPR, integer_type_node, packed);
5323 14067 : nthreads = fold_convert (itype, nthreads);
5324 14067 : nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
5325 : true, GSI_SAME_STMT);
5326 : }
5327 :
5328 14067 : q = create_tmp_reg (itype, "q");
5329 14067 : t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
5330 14067 : t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5331 14067 : gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
5332 :
5333 14067 : tt = create_tmp_reg (itype, "tt");
5334 14067 : t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
5335 14067 : t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5336 14067 : gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
5337 :
5338 14067 : t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
5339 14067 : gcond *cond_stmt = gimple_build_cond_empty (t);
5340 14067 : gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
5341 :
5342 14067 : second_bb = split_block (entry_bb, cond_stmt)->dest;
5343 14067 : gsi = gsi_last_nondebug_bb (second_bb);
5344 14067 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5345 :
5346 14067 : gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
5347 : GSI_SAME_STMT);
5348 14067 : gassign *assign_stmt
5349 14067 : = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
5350 14067 : gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
5351 :
5352 14067 : third_bb = split_block (second_bb, assign_stmt)->dest;
5353 14067 : gsi = gsi_last_nondebug_bb (third_bb);
5354 14067 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5355 :
5356 14067 : if (fd->have_nonctrl_scantemp)
5357 : {
5358 185 : tree clauses = gimple_omp_for_clauses (fd->for_stmt);
5359 185 : tree controlp = NULL_TREE, controlb = NULL_TREE;
5360 804 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5361 804 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__SCANTEMP_
5362 804 : && OMP_CLAUSE__SCANTEMP__CONTROL (c))
5363 : {
5364 370 : if (TREE_TYPE (OMP_CLAUSE_DECL (c)) == boolean_type_node)
5365 185 : controlb = OMP_CLAUSE_DECL (c);
5366 : else
5367 185 : controlp = OMP_CLAUSE_DECL (c);
5368 370 : if (controlb && controlp)
5369 : break;
5370 : }
5371 185 : gcc_assert (controlp && controlb);
5372 185 : tree cnt = create_tmp_var (sizetype);
5373 185 : gimple *g = gimple_build_assign (cnt, NOP_EXPR, q);
5374 185 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5375 185 : unsigned HOST_WIDE_INT alloc_align = TYPE_ALIGN_UNIT (ptr_type_node);
5376 185 : tree sz = expand_omp_scantemp_alloc (clauses, NULL_TREE, 0,
5377 : alloc_align, cnt, NULL, true);
5378 185 : tree size = create_tmp_var (sizetype);
5379 185 : expand_omp_build_assign (&gsi, size, sz, false);
5380 185 : tree cmp = fold_build2 (GT_EXPR, boolean_type_node,
5381 : size, size_int (16384));
5382 185 : expand_omp_build_assign (&gsi, controlb, cmp);
5383 185 : g = gimple_build_cond (NE_EXPR, controlb, boolean_false_node,
5384 : NULL_TREE, NULL_TREE);
5385 185 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5386 185 : fourth_bb = split_block (third_bb, g)->dest;
5387 185 : gsi = gsi_last_nondebug_bb (fourth_bb);
5388 : /* FIXME: Once we have allocators, this should use allocator. */
5389 185 : g = gimple_build_call (builtin_decl_explicit (BUILT_IN_MALLOC), 1, size);
5390 185 : gimple_call_set_lhs (g, controlp);
5391 185 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5392 185 : expand_omp_scantemp_alloc (clauses, controlp, 0, alloc_align, cnt,
5393 : &gsi, true);
5394 185 : gsi_prev (&gsi);
5395 185 : g = gsi_stmt (gsi);
5396 185 : fifth_bb = split_block (fourth_bb, g)->dest;
5397 185 : gsi = gsi_last_nondebug_bb (fifth_bb);
5398 :
5399 370 : g = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
5400 185 : gimple_call_set_lhs (g, controlp);
5401 185 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5402 185 : tree alloca_decl = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
5403 1522 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5404 1337 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__SCANTEMP_
5405 1337 : && OMP_CLAUSE__SCANTEMP__ALLOC (c))
5406 : {
5407 217 : tree tmp = create_tmp_var (sizetype);
5408 217 : tree pointee_type = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
5409 217 : g = gimple_build_assign (tmp, MULT_EXPR, cnt,
5410 217 : TYPE_SIZE_UNIT (pointee_type));
5411 217 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5412 217 : g = gimple_build_call (alloca_decl, 2, tmp,
5413 217 : size_int (TYPE_ALIGN (pointee_type)));
5414 217 : gimple_call_set_lhs (g, OMP_CLAUSE_DECL (c));
5415 217 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5416 : }
5417 :
5418 185 : sixth_bb = split_block (fifth_bb, g)->dest;
5419 185 : gsi = gsi_last_nondebug_bb (sixth_bb);
5420 : }
5421 :
5422 14067 : t = build2 (MULT_EXPR, itype, q, threadid);
5423 14067 : t = build2 (PLUS_EXPR, itype, t, tt);
5424 14067 : s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5425 :
5426 14067 : t = fold_build2 (PLUS_EXPR, itype, s0, q);
5427 14067 : e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5428 :
5429 14067 : t = build2 (GE_EXPR, boolean_type_node, s0, e0);
5430 14067 : gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5431 :
5432 : /* Remove the GIMPLE_OMP_FOR statement. */
5433 14067 : gsi_remove (&gsi, true);
5434 :
5435 : /* Setup code for sequential iteration goes in SEQ_START_BB. */
5436 14067 : gsi = gsi_start_bb (seq_start_bb);
5437 :
5438 14067 : tree startvar = fd->loop.v;
5439 14067 : tree endvar = NULL_TREE;
5440 :
5441 14067 : if (gimple_omp_for_combined_p (fd->for_stmt))
5442 : {
5443 7112 : tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5444 10668 : ? gimple_omp_parallel_clauses (inner_stmt)
5445 3556 : : gimple_omp_for_clauses (inner_stmt);
5446 7112 : tree innerc = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5447 7112 : gcc_assert (innerc);
5448 7112 : startvar = OMP_CLAUSE_DECL (innerc);
5449 7112 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
5450 : OMP_CLAUSE__LOOPTEMP_);
5451 7112 : gcc_assert (innerc);
5452 7112 : endvar = OMP_CLAUSE_DECL (innerc);
5453 2311 : if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
5454 8434 : && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5455 : {
5456 829 : innerc = find_lastprivate_looptemp (fd, innerc);
5457 829 : if (innerc)
5458 : {
5459 : /* If needed (distribute parallel for with lastprivate),
5460 : propagate down the total number of iterations. */
5461 375 : tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
5462 : fd->loop.n2);
5463 375 : t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
5464 : GSI_CONTINUE_LINKING);
5465 375 : assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
5466 375 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5467 : }
5468 : }
5469 : }
5470 14067 : t = fold_convert (itype, s0);
5471 14067 : t = fold_build2 (MULT_EXPR, itype, t, step);
5472 14067 : if (POINTER_TYPE_P (type))
5473 : {
5474 606 : t = fold_build_pointer_plus (n1, t);
5475 670 : if (!POINTER_TYPE_P (TREE_TYPE (startvar))
5476 670 : && TYPE_PRECISION (TREE_TYPE (startvar)) > TYPE_PRECISION (type))
5477 0 : t = fold_convert (signed_type_for (type), t);
5478 : }
5479 : else
5480 13461 : t = fold_build2 (PLUS_EXPR, type, t, n1);
5481 14067 : t = fold_convert (TREE_TYPE (startvar), t);
5482 14067 : t = force_gimple_operand_gsi (&gsi, t,
5483 14067 : DECL_P (startvar)
5484 13897 : && TREE_ADDRESSABLE (startvar),
5485 : NULL_TREE, false, GSI_CONTINUE_LINKING);
5486 14067 : assign_stmt = gimple_build_assign (startvar, t);
5487 14067 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5488 14067 : if (cond_var)
5489 : {
5490 108 : tree itype = TREE_TYPE (cond_var);
5491 : /* For lastprivate(conditional:) itervar, we need some iteration
5492 : counter that starts at unsigned non-zero and increases.
5493 : Prefer as few IVs as possible, so if we can use startvar
5494 : itself, use that, or startvar + constant (those would be
5495 : incremented with step), and as last resort use the s0 + 1
5496 : incremented by 1. */
5497 108 : if (POINTER_TYPE_P (type)
5498 108 : || TREE_CODE (n1) != INTEGER_CST
5499 102 : || fd->loop.cond_code != LT_EXPR)
5500 6 : t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, s0),
5501 : build_int_cst (itype, 1));
5502 102 : else if (tree_int_cst_sgn (n1) == 1)
5503 12 : t = fold_convert (itype, t);
5504 : else
5505 : {
5506 90 : tree c = fold_convert (itype, n1);
5507 90 : c = fold_build2 (MINUS_EXPR, itype, build_int_cst (itype, 1), c);
5508 90 : t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, t), c);
5509 : }
5510 108 : t = force_gimple_operand_gsi (&gsi, t, false,
5511 : NULL_TREE, false, GSI_CONTINUE_LINKING);
5512 108 : assign_stmt = gimple_build_assign (cond_var, t);
5513 108 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5514 : }
5515 :
5516 14067 : t = fold_convert (itype, e0);
5517 14067 : t = fold_build2 (MULT_EXPR, itype, t, step);
5518 14067 : if (POINTER_TYPE_P (type))
5519 : {
5520 606 : t = fold_build_pointer_plus (n1, t);
5521 670 : if (!POINTER_TYPE_P (TREE_TYPE (startvar))
5522 670 : && TYPE_PRECISION (TREE_TYPE (startvar)) > TYPE_PRECISION (type))
5523 0 : t = fold_convert (signed_type_for (type), t);
5524 : }
5525 : else
5526 13461 : t = fold_build2 (PLUS_EXPR, type, t, n1);
5527 14067 : t = fold_convert (TREE_TYPE (startvar), t);
5528 14067 : e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5529 : false, GSI_CONTINUE_LINKING);
5530 14067 : if (endvar)
5531 : {
5532 7112 : assign_stmt = gimple_build_assign (endvar, e);
5533 7112 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5534 7112 : if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
5535 6343 : assign_stmt = gimple_build_assign (fd->loop.v, e);
5536 : else
5537 769 : assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
5538 7112 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5539 : }
5540 : /* Handle linear clause adjustments. */
5541 14067 : tree itercnt = NULL_TREE;
5542 14067 : tree *nonrect_bounds = NULL;
5543 14067 : if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
5544 45461 : for (tree c = gimple_omp_for_clauses (fd->for_stmt);
5545 45461 : c; c = OMP_CLAUSE_CHAIN (c))
5546 35967 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5547 35967 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
5548 : {
5549 87 : tree d = OMP_CLAUSE_DECL (c);
5550 87 : tree t = d, a, dest;
5551 87 : if (omp_privatize_by_reference (t))
5552 13 : t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
5553 87 : if (itercnt == NULL_TREE)
5554 : {
5555 87 : if (gimple_omp_for_combined_into_p (fd->for_stmt))
5556 : {
5557 0 : itercnt = fold_build2 (MINUS_EXPR, itype,
5558 : fold_convert (itype, n1),
5559 : fold_convert (itype, fd->loop.n1));
5560 0 : itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
5561 0 : itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
5562 0 : itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
5563 : NULL_TREE, false,
5564 : GSI_CONTINUE_LINKING);
5565 : }
5566 : else
5567 : itercnt = s0;
5568 : }
5569 87 : tree type = TREE_TYPE (t);
5570 87 : if (POINTER_TYPE_P (type))
5571 0 : type = sizetype;
5572 87 : a = fold_build2 (MULT_EXPR, type,
5573 : fold_convert (type, itercnt),
5574 : fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
5575 87 : dest = unshare_expr (t);
5576 87 : t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
5577 : : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
5578 87 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5579 : false, GSI_CONTINUE_LINKING);
5580 87 : expand_omp_build_assign (&gsi, dest, t, true);
5581 : }
5582 14067 : if (fd->collapse > 1)
5583 : {
5584 3921 : if (fd->non_rect)
5585 : {
5586 376 : nonrect_bounds = XALLOCAVEC (tree, fd->last_nonrect + 1);
5587 376 : memset (nonrect_bounds, 0, sizeof (tree) * (fd->last_nonrect + 1));
5588 : }
5589 3921 : expand_omp_for_init_vars (fd, &gsi, counts, nonrect_bounds, inner_stmt,
5590 : startvar);
5591 : }
5592 :
5593 14067 : if (!broken_loop)
5594 : {
5595 : /* The code controlling the sequential loop replaces the
5596 : GIMPLE_OMP_CONTINUE. */
5597 13571 : gsi = gsi_last_nondebug_bb (cont_bb);
5598 13571 : gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
5599 13571 : gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
5600 13571 : vmain = gimple_omp_continue_control_use (cont_stmt);
5601 13571 : vback = gimple_omp_continue_control_def (cont_stmt);
5602 :
5603 13571 : if (cond_var)
5604 : {
5605 108 : tree itype = TREE_TYPE (cond_var);
5606 108 : tree t2;
5607 108 : if (POINTER_TYPE_P (type)
5608 108 : || TREE_CODE (n1) != INTEGER_CST
5609 102 : || fd->loop.cond_code != LT_EXPR)
5610 6 : t2 = build_int_cst (itype, 1);
5611 : else
5612 102 : t2 = fold_convert (itype, step);
5613 108 : t2 = fold_build2 (PLUS_EXPR, itype, cond_var, t2);
5614 108 : t2 = force_gimple_operand_gsi (&gsi, t2, false,
5615 : NULL_TREE, true, GSI_SAME_STMT);
5616 108 : assign_stmt = gimple_build_assign (cond_var, t2);
5617 108 : gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
5618 : }
5619 :
5620 13571 : if (!gimple_omp_for_combined_p (fd->for_stmt))
5621 : {
5622 6459 : if (POINTER_TYPE_P (type))
5623 316 : t = fold_build_pointer_plus (vmain, step);
5624 : else
5625 6143 : t = fold_build2 (PLUS_EXPR, type, vmain, step);
5626 6459 : t = force_gimple_operand_gsi (&gsi, t,
5627 6459 : DECL_P (vback)
5628 6289 : && TREE_ADDRESSABLE (vback),
5629 : NULL_TREE, true, GSI_SAME_STMT);
5630 6459 : assign_stmt = gimple_build_assign (vback, t);
5631 6459 : gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
5632 :
5633 6459 : t = build2 (fd->loop.cond_code, boolean_type_node,
5634 6459 : DECL_P (vback) && TREE_ADDRESSABLE (vback)
5635 : ? t : vback, e);
5636 6459 : gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5637 : }
5638 :
5639 : /* Remove the GIMPLE_OMP_CONTINUE statement. */
5640 13571 : gsi_remove (&gsi, true);
5641 :
5642 13571 : if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5643 1382 : collapse_bb = extract_omp_for_update_vars (fd, nonrect_bounds,
5644 : cont_bb, body_bb);
5645 : }
5646 :
5647 14067 : if (flag_openmp_ompt == OMP_OMPT_LEVEL_EXTENDED)
5648 : {
5649 : /* Insert call to GOMP_*_static_worksharing_dispatch at the end of
5650 : seq_start_bb. */
5651 8 : gsi = gsi_last_nondebug_bb (seq_start_bb);
5652 8 : tree decl;
5653 8 : switch (gimple_omp_for_kind (fd->for_stmt))
5654 : {
5655 4 : case GF_OMP_FOR_KIND_FOR:
5656 4 : decl = builtin_decl_explicit (
5657 : BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_DISPATCH);
5658 4 : break;
5659 4 : case GF_OMP_FOR_KIND_DISTRIBUTE:
5660 4 : decl = builtin_decl_explicit (
5661 : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_DISPATCH);
5662 4 : break;
5663 0 : default:
5664 0 : gcc_unreachable ();
5665 : }
5666 8 : tree s0_ull = fold_convert (long_long_unsigned_type_node, s0);
5667 8 : tree q_ull = fold_convert (long_long_unsigned_type_node, q);
5668 8 : tree call = build_call_expr (decl, 2, s0_ull, q_ull);
5669 8 : force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true,
5670 : GSI_SAME_STMT);
5671 : }
5672 :
5673 14067 : gsi = gsi_last_nondebug_bb (exit_bb);
5674 14067 : if (flag_openmp_ompt && !has_gomp_loop_end)
5675 : {
5676 : /* Insert call to GOMP_*_static_worksharing_end at the end of exit_bb.
5677 : */
5678 20 : tree decl;
5679 20 : switch (gimple_omp_for_kind (fd->for_stmt))
5680 : {
5681 12 : case GF_OMP_FOR_KIND_FOR:
5682 12 : decl
5683 12 : = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_END);
5684 12 : break;
5685 8 : case GF_OMP_FOR_KIND_DISTRIBUTE:
5686 8 : decl = builtin_decl_explicit (
5687 : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_END);
5688 8 : break;
5689 0 : default:
5690 0 : gcc_unreachable ();
5691 : }
5692 20 : gcall *g = gimple_build_call (decl, 0);
5693 20 : gsi_insert_after (&gsi, g, GSI_SAME_STMT);
5694 : }
5695 :
5696 : /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
5697 14067 : if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5698 : {
5699 2399 : t = gimple_omp_return_lhs (gsi_stmt (gsi));
5700 2399 : if (fd->have_reductemp
5701 2346 : || ((fd->have_pointer_condtemp || fd->have_scantemp)
5702 63 : && !fd->have_nonctrl_scantemp))
5703 : {
5704 116 : tree fn;
5705 116 : if (t)
5706 4 : fn = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5707 : else
5708 112 : fn = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5709 116 : gcall *g = gimple_build_call (fn, 0);
5710 116 : if (t)
5711 : {
5712 4 : gimple_call_set_lhs (g, t);
5713 4 : if (fd->have_reductemp)
5714 4 : gsi_insert_after (&gsi, gimple_build_assign (reductions,
5715 : NOP_EXPR, t),
5716 : GSI_SAME_STMT);
5717 : }
5718 116 : gsi_insert_after (&gsi, g, GSI_SAME_STMT);
5719 116 : }
5720 : else
5721 2283 : gsi_insert_after (&gsi,
5722 : omp_build_barrier (t,
5723 : GOMP_BARRIER_IMPLICIT_WORKSHARE),
5724 : GSI_SAME_STMT);
5725 : }
5726 11668 : else if ((fd->have_pointer_condtemp || fd->have_scantemp)
5727 325 : && !fd->have_nonctrl_scantemp)
5728 : {
5729 140 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5730 140 : gcall *g = gimple_build_call (fn, 0);
5731 140 : gsi_insert_after (&gsi, g, GSI_SAME_STMT);
5732 : }
5733 14067 : if (fd->have_scantemp && !fd->have_nonctrl_scantemp)
5734 : {
5735 185 : tree clauses = gimple_omp_for_clauses (fd->for_stmt);
5736 185 : tree controlp = NULL_TREE, controlb = NULL_TREE;
5737 370 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5738 370 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__SCANTEMP_
5739 370 : && OMP_CLAUSE__SCANTEMP__CONTROL (c))
5740 : {
5741 370 : if (TREE_TYPE (OMP_CLAUSE_DECL (c)) == boolean_type_node)
5742 185 : controlb = OMP_CLAUSE_DECL (c);
5743 : else
5744 185 : controlp = OMP_CLAUSE_DECL (c);
5745 370 : if (controlb && controlp)
5746 : break;
5747 : }
5748 185 : gcc_assert (controlp && controlb);
5749 185 : gimple *g = gimple_build_cond (NE_EXPR, controlb, boolean_false_node,
5750 : NULL_TREE, NULL_TREE);
5751 185 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5752 185 : exit1_bb = split_block (exit_bb, g)->dest;
5753 185 : gsi = gsi_after_labels (exit1_bb);
5754 185 : g = gimple_build_call (builtin_decl_explicit (BUILT_IN_FREE), 1,
5755 : controlp);
5756 185 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5757 185 : exit2_bb = split_block (exit1_bb, g)->dest;
5758 185 : gsi = gsi_after_labels (exit2_bb);
5759 370 : g = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE), 1,
5760 : controlp);
5761 185 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5762 185 : exit3_bb = split_block (exit2_bb, g)->dest;
5763 185 : gsi = gsi_after_labels (exit3_bb);
5764 : }
5765 :
5766 14067 : gsi_remove (&gsi, true);
5767 :
5768 : /* Connect all the blocks. */
5769 14067 : ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
5770 14067 : ep->probability = profile_probability::guessed_always ().apply_scale (3, 4);
5771 14067 : ep = find_edge (entry_bb, second_bb);
5772 14067 : ep->flags = EDGE_TRUE_VALUE;
5773 14067 : ep->probability = profile_probability::guessed_always () / 4;
5774 14067 : if (fourth_bb)
5775 : {
5776 185 : ep = make_edge (third_bb, fifth_bb, EDGE_FALSE_VALUE);
5777 185 : ep->probability = profile_probability::guessed_always () / 2;
5778 185 : ep = find_edge (third_bb, fourth_bb);
5779 185 : ep->flags = EDGE_TRUE_VALUE;
5780 185 : ep->probability = profile_probability::guessed_always () / 2;
5781 185 : ep = find_edge (fourth_bb, fifth_bb);
5782 185 : redirect_edge_and_branch (ep, sixth_bb);
5783 : }
5784 : else
5785 : sixth_bb = third_bb;
5786 14067 : find_edge (sixth_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
5787 14067 : find_edge (sixth_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
5788 14067 : if (exit1_bb)
5789 : {
5790 185 : ep = make_edge (exit_bb, exit2_bb, EDGE_FALSE_VALUE);
5791 185 : ep->probability = profile_probability::guessed_always () / 2;
5792 185 : ep = find_edge (exit_bb, exit1_bb);
5793 185 : ep->flags = EDGE_TRUE_VALUE;
5794 185 : ep->probability = profile_probability::guessed_always () / 2;
5795 185 : ep = find_edge (exit1_bb, exit2_bb);
5796 185 : redirect_edge_and_branch (ep, exit3_bb);
5797 : }
5798 :
5799 14067 : if (!broken_loop)
5800 : {
5801 13571 : ep = find_edge (cont_bb, body_bb);
5802 13571 : if (ep == NULL)
5803 : {
5804 170 : ep = BRANCH_EDGE (cont_bb);
5805 170 : gcc_assert (single_succ (ep->dest) == body_bb);
5806 : }
5807 13571 : if (gimple_omp_for_combined_p (fd->for_stmt))
5808 : {
5809 7112 : remove_edge (ep);
5810 7112 : ep = NULL;
5811 : }
5812 6459 : else if (fd->collapse > 1)
5813 : {
5814 1382 : remove_edge (ep);
5815 1382 : ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5816 : }
5817 : else
5818 5077 : ep->flags = EDGE_TRUE_VALUE;
5819 20683 : find_edge (cont_bb, fin_bb)->flags
5820 14953 : = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
5821 : }
5822 :
5823 14067 : set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
5824 14067 : set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
5825 14067 : if (fourth_bb)
5826 : {
5827 185 : set_immediate_dominator (CDI_DOMINATORS, fifth_bb, third_bb);
5828 185 : set_immediate_dominator (CDI_DOMINATORS, sixth_bb, third_bb);
5829 : }
5830 14067 : set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, sixth_bb);
5831 :
5832 14067 : set_immediate_dominator (CDI_DOMINATORS, body_bb,
5833 : recompute_dominator (CDI_DOMINATORS, body_bb));
5834 14067 : set_immediate_dominator (CDI_DOMINATORS, fin_bb,
5835 : recompute_dominator (CDI_DOMINATORS, fin_bb));
5836 14067 : if (exit1_bb)
5837 : {
5838 185 : set_immediate_dominator (CDI_DOMINATORS, exit2_bb, exit_bb);
5839 185 : set_immediate_dominator (CDI_DOMINATORS, exit3_bb, exit_bb);
5840 : }
5841 :
5842 14067 : class loop *loop = body_bb->loop_father;
5843 14067 : if (loop != entry_bb->loop_father)
5844 : {
5845 332 : gcc_assert (broken_loop || loop->header == body_bb);
5846 170 : gcc_assert (broken_loop
5847 : || loop->latch == region->cont
5848 : || single_pred (loop->latch) == region->cont);
5849 332 : return;
5850 : }
5851 :
5852 13735 : if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
5853 : {
5854 6289 : loop = alloc_loop ();
5855 6289 : loop->header = body_bb;
5856 6289 : if (collapse_bb == NULL)
5857 4907 : loop->latch = cont_bb;
5858 6289 : add_loop (loop, body_bb->loop_father);
5859 : }
5860 : }
5861 :
5862 : /* Return phi in E->DEST with ARG on edge E. */
5863 :
5864 : static gphi *
5865 14 : find_phi_with_arg_on_edge (tree arg, edge e)
5866 : {
5867 14 : basic_block bb = e->dest;
5868 :
5869 14 : for (gphi_iterator gpi = gsi_start_phis (bb);
5870 14 : !gsi_end_p (gpi);
5871 0 : gsi_next (&gpi))
5872 : {
5873 14 : gphi *phi = gpi.phi ();
5874 14 : if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
5875 14 : return phi;
5876 : }
5877 :
5878 0 : return NULL;
5879 : }
5880 :
5881 : /* A subroutine of expand_omp_for. Generate code for a parallel
5882 : loop with static schedule and a specified chunk size. Given
5883 : parameters:
5884 :
5885 : for (V = N1; V cond N2; V += STEP) BODY;
5886 :
5887 : where COND is "<" or ">", we generate pseudocode
5888 :
5889 : if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5890 : if (cond is <)
5891 : adj = STEP - 1;
5892 : else
5893 : adj = STEP + 1;
5894 : if ((__typeof (V)) -1 > 0 && cond is >)
5895 : n = -(adj + N2 - N1) / -STEP;
5896 : else
5897 : n = (adj + N2 - N1) / STEP;
5898 : trip = 0;
5899 : V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
5900 : here so that V is defined
5901 : if the loop is not entered
5902 : L0:
5903 : s0 = (trip * nthreads + threadid) * CHUNK;
5904 : e0 = min (s0 + CHUNK, n);
5905 : if (s0 < n) goto L1; else goto L4;
5906 : L1:
5907 : V = s0 * STEP + N1;
5908 : e = e0 * STEP + N1;
5909 : L2:
5910 : BODY;
5911 : V += STEP;
5912 : if (V cond e) goto L2; else goto L3;
5913 : L3:
5914 : trip += 1;
5915 : goto L0;
5916 : L4:
5917 : */
5918 :
5919 : static void
5920 5855 : expand_omp_for_static_chunk (struct omp_region *region,
5921 : struct omp_for_data *fd, gimple *inner_stmt)
5922 : {
5923 5855 : tree n, s0, e0, e, t;
5924 5855 : tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
5925 5855 : tree type, itype, vmain, vback, vextra;
5926 5855 : basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
5927 5855 : basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
5928 5855 : gimple_stmt_iterator gsi, gsip;
5929 5855 : edge se;
5930 5855 : bool broken_loop = region->cont == NULL;
5931 5855 : tree *counts = NULL;
5932 5855 : tree n1, n2, step;
5933 5855 : tree reductions = NULL_TREE;
5934 5855 : tree cond_var = NULL_TREE, condtemp = NULL_TREE;
5935 :
5936 5855 : itype = type = TREE_TYPE (fd->loop.v);
5937 5855 : if (POINTER_TYPE_P (type))
5938 316 : itype = signed_type_for (type);
5939 :
5940 5855 : entry_bb = region->entry;
5941 5855 : se = split_block (entry_bb, last_nondebug_stmt (entry_bb));
5942 5855 : entry_bb = se->src;
5943 5855 : iter_part_bb = se->dest;
5944 5855 : cont_bb = region->cont;
5945 5855 : gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
5946 5855 : fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
5947 5855 : gcc_assert (broken_loop
5948 : || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
5949 5855 : seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
5950 5855 : body_bb = single_succ (seq_start_bb);
5951 5855 : if (!broken_loop)
5952 : {
5953 5598 : gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
5954 : || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
5955 5598 : gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5956 5598 : trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
5957 : }
5958 5855 : exit_bb = region->exit;
5959 :
5960 : /* Trip and adjustment setup goes in ENTRY_BB. */
5961 5855 : gsi = gsi_last_nondebug_bb (entry_bb);
5962 5855 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5963 5855 : gsip = gsi;
5964 5855 : gsi_prev (&gsip);
5965 :
5966 5855 : if (fd->collapse > 1)
5967 : {
5968 2232 : int first_zero_iter = -1, dummy = -1;
5969 2232 : basic_block l2_dom_bb = NULL, dummy_bb = NULL;
5970 :
5971 2232 : counts = XALLOCAVEC (tree, fd->collapse);
5972 2232 : expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5973 : fin_bb, first_zero_iter,
5974 : dummy_bb, dummy, l2_dom_bb);
5975 2232 : t = NULL_TREE;
5976 : }
5977 3623 : else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5978 813 : t = integer_one_node;
5979 : else
5980 2810 : t = fold_binary (fd->loop.cond_code, boolean_type_node,
5981 : fold_convert (type, fd->loop.n1),
5982 : fold_convert (type, fd->loop.n2));
5983 5855 : if (fd->collapse == 1
5984 3623 : && TYPE_UNSIGNED (type)
5985 7042 : && (t == NULL_TREE || !integer_onep (t)))
5986 : {
5987 236 : n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5988 236 : n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5989 : true, GSI_SAME_STMT);
5990 236 : n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5991 236 : n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5992 : true, GSI_SAME_STMT);
5993 236 : gcond *cond_stmt = expand_omp_build_cond (&gsi, fd->loop.cond_code,
5994 : n1, n2);
5995 236 : se = split_block (entry_bb, cond_stmt);
5996 236 : se->flags = EDGE_TRUE_VALUE;
5997 236 : entry_bb = se->dest;
5998 236 : se->probability = profile_probability::very_likely ();
5999 236 : se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6000 236 : se->probability = profile_probability::very_unlikely ();
6001 236 : if (gimple_in_ssa_p (cfun))
6002 : {
6003 1 : int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
6004 1 : for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6005 2 : !gsi_end_p (gpi); gsi_next (&gpi))
6006 : {
6007 1 : gphi *phi = gpi.phi ();
6008 1 : add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6009 : se, UNKNOWN_LOCATION);
6010 : }
6011 : }
6012 472 : gsi = gsi_last_bb (entry_bb);
6013 : }
6014 :
6015 5855 : if (fd->lastprivate_conditional)
6016 : {
6017 49 : tree clauses = gimple_omp_for_clauses (fd->for_stmt);
6018 49 : tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
6019 49 : if (fd->have_pointer_condtemp)
6020 29 : condtemp = OMP_CLAUSE_DECL (c);
6021 49 : c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE__CONDTEMP_);
6022 49 : cond_var = OMP_CLAUSE_DECL (c);
6023 : }
6024 5855 : if (fd->have_reductemp || fd->have_pointer_condtemp)
6025 : {
6026 44 : tree t1 = build_int_cst (long_integer_type_node, 0);
6027 44 : tree t2 = build_int_cst (long_integer_type_node, 1);
6028 44 : tree t3 = build_int_cstu (long_integer_type_node,
6029 : (HOST_WIDE_INT_1U << 31) + 1);
6030 44 : tree clauses = gimple_omp_for_clauses (fd->for_stmt);
6031 44 : gimple_stmt_iterator gsi2 = gsi_none ();
6032 44 : gimple *g = NULL;
6033 44 : tree mem = null_pointer_node, memv = NULL_TREE;
6034 44 : if (fd->have_reductemp)
6035 : {
6036 25 : tree c = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
6037 25 : reductions = OMP_CLAUSE_DECL (c);
6038 25 : gcc_assert (TREE_CODE (reductions) == SSA_NAME);
6039 25 : g = SSA_NAME_DEF_STMT (reductions);
6040 25 : reductions = gimple_assign_rhs1 (g);
6041 25 : OMP_CLAUSE_DECL (c) = reductions;
6042 25 : gsi2 = gsi_for_stmt (g);
6043 : }
6044 : else
6045 : {
6046 19 : if (gsi_end_p (gsip))
6047 0 : gsi2 = gsi_after_labels (region->entry);
6048 : else
6049 19 : gsi2 = gsip;
6050 : reductions = null_pointer_node;
6051 : }
6052 44 : if (fd->have_pointer_condtemp)
6053 : {
6054 29 : tree type = TREE_TYPE (condtemp);
6055 29 : memv = create_tmp_var (type);
6056 29 : TREE_ADDRESSABLE (memv) = 1;
6057 29 : unsigned HOST_WIDE_INT sz
6058 29 : = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
6059 29 : sz *= fd->lastprivate_conditional;
6060 29 : expand_omp_build_assign (&gsi2, memv, build_int_cst (type, sz),
6061 : false);
6062 29 : mem = build_fold_addr_expr (memv);
6063 : }
6064 44 : tree t
6065 44 : = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_LOOP_START),
6066 : 9, t1, t2, t2, t3, t1, null_pointer_node,
6067 : null_pointer_node, reductions, mem);
6068 44 : force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
6069 : true, GSI_SAME_STMT);
6070 44 : if (fd->have_pointer_condtemp)
6071 29 : expand_omp_build_assign (&gsi2, condtemp, memv, false);
6072 44 : if (fd->have_reductemp)
6073 : {
6074 25 : gsi_remove (&gsi2, true);
6075 25 : release_ssa_name (gimple_assign_lhs (g));
6076 : }
6077 : }
6078 :
6079 5855 : n1 = fd->loop.n1;
6080 5855 : n2 = fd->loop.n2;
6081 5855 : step = fd->loop.step;
6082 5855 : if (gimple_omp_for_combined_into_p (fd->for_stmt))
6083 : {
6084 1301 : tree innerc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
6085 : OMP_CLAUSE__LOOPTEMP_);
6086 1301 : gcc_assert (innerc);
6087 1301 : n1 = OMP_CLAUSE_DECL (innerc);
6088 1301 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
6089 : OMP_CLAUSE__LOOPTEMP_);
6090 1301 : gcc_assert (innerc);
6091 1301 : n2 = OMP_CLAUSE_DECL (innerc);
6092 : }
6093 5855 : n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6094 : true, NULL_TREE, true, GSI_SAME_STMT);
6095 5855 : n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6096 : true, NULL_TREE, true, GSI_SAME_STMT);
6097 5855 : step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6098 : true, NULL_TREE, true, GSI_SAME_STMT);
6099 5855 : tree chunk_size = fold_convert (itype, fd->chunk_size);
6100 5855 : chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule,
6101 : is_in_offload_region (region));
6102 5855 : chunk_size
6103 5855 : = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
6104 : GSI_SAME_STMT);
6105 :
6106 6461 : t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6107 5855 : t = fold_build2 (PLUS_EXPR, itype, step, t);
6108 5855 : t = fold_build2 (PLUS_EXPR, itype, t, n2);
6109 5855 : t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6110 5855 : if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6111 284 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
6112 : fold_build1 (NEGATE_EXPR, itype, t),
6113 : fold_build1 (NEGATE_EXPR, itype, step));
6114 : else
6115 5571 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6116 5855 : t = fold_convert (itype, t);
6117 5855 : n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6118 : true, GSI_SAME_STMT);
6119 :
6120 : /* When GOMP_loop_end (or one of its variants) is emitted (e.g. with the
6121 : inscan modifier), which already implies the end of the scope, _start
6122 : variants of GOMP builtin calls have to be used and _end can be skipped. */
6123 5855 : bool has_gomp_loop_end = fd->have_reductemp || fd->have_pointer_condtemp;
6124 5855 : {
6125 : /* Fetch the thread/team id and the number of threads/teams in a single
6126 : call to GOMP_loop_static_worksharing or
6127 : GOMP_distribute_static_worksharing. The helper returns both values packed
6128 : into one complex int, with the id as the imaginary part and the count as
6129 : the real part. Returning (rather than writing through pointers) keeps
6130 : both values as plain SSA names, which lets later passes - notably IPA-CP
6131 : propagating constants into the outlined kernel - reason about them.
6132 : Also pass the total number of iterations for OMPT. */
6133 5855 : tree decl;
6134 5855 : switch (gimple_omp_for_kind (fd->for_stmt))
6135 : {
6136 2385 : case GF_OMP_FOR_KIND_FOR:
6137 4770 : decl = builtin_decl_explicit (
6138 2385 : flag_openmp_ompt || has_gomp_loop_end
6139 : ? BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_START
6140 : : BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING);
6141 2385 : break;
6142 3470 : case GF_OMP_FOR_KIND_DISTRIBUTE:
6143 6940 : decl = builtin_decl_explicit (
6144 3470 : flag_openmp_ompt || has_gomp_loop_end
6145 : ? BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_START
6146 : : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING);
6147 3470 : break;
6148 0 : default:
6149 0 : gcc_unreachable ();
6150 : }
6151 5855 : tree n_ull = fold_convert (long_long_unsigned_type_node, n);
6152 5855 : tree packed = build_call_expr (decl, 1, n_ull);
6153 5855 : packed = force_gimple_operand_gsi (&gsi, packed, true, NULL_TREE, true,
6154 : GSI_SAME_STMT);
6155 5855 : threadid = fold_build1 (IMAGPART_EXPR, integer_type_node, packed);
6156 5855 : threadid = fold_convert (itype, threadid);
6157 5855 : threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE, true,
6158 : GSI_SAME_STMT);
6159 5855 : nthreads = fold_build1 (REALPART_EXPR, integer_type_node, packed);
6160 5855 : nthreads = fold_convert (itype, nthreads);
6161 5855 : nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE, true,
6162 : GSI_SAME_STMT);
6163 : }
6164 :
6165 5855 : trip_var = create_tmp_reg (itype, ".trip");
6166 5855 : if (gimple_in_ssa_p (cfun))
6167 : {
6168 12 : trip_init = make_ssa_name (trip_var);
6169 12 : trip_main = make_ssa_name (trip_var);
6170 12 : trip_back = make_ssa_name (trip_var);
6171 : }
6172 : else
6173 : {
6174 : trip_init = trip_var;
6175 : trip_main = trip_var;
6176 : trip_back = trip_var;
6177 : }
6178 :
6179 5855 : gassign *assign_stmt
6180 5855 : = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6181 5855 : gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6182 :
6183 5855 : t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
6184 5855 : t = fold_build2 (MULT_EXPR, itype, t, step);
6185 5855 : if (POINTER_TYPE_P (type))
6186 316 : t = fold_build_pointer_plus (n1, t);
6187 : else
6188 5539 : t = fold_build2 (PLUS_EXPR, type, t, n1);
6189 5855 : vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6190 : true, GSI_SAME_STMT);
6191 :
6192 : /* Remove the GIMPLE_OMP_FOR. */
6193 5855 : gsi_remove (&gsi, true);
6194 :
6195 5855 : gimple_stmt_iterator gsif = gsi;
6196 :
6197 : /* Iteration space partitioning goes in ITER_PART_BB. */
6198 5855 : gsi = gsi_last_bb (iter_part_bb);
6199 :
6200 5855 : t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6201 5855 : t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6202 5855 : t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
6203 5855 : s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6204 : false, GSI_CONTINUE_LINKING);
6205 :
6206 5855 : t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
6207 5855 : t = fold_build2 (MIN_EXPR, itype, t, n);
6208 5855 : e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6209 : false, GSI_CONTINUE_LINKING);
6210 :
6211 5855 : t = build2 (LT_EXPR, boolean_type_node, s0, n);
6212 5855 : gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6213 :
6214 : /* Setup code for sequential iteration goes in SEQ_START_BB. */
6215 5855 : gsi = gsi_start_bb (seq_start_bb);
6216 :
6217 5855 : tree startvar = fd->loop.v;
6218 5855 : tree endvar = NULL_TREE;
6219 :
6220 5855 : if (gimple_omp_for_combined_p (fd->for_stmt))
6221 : {
6222 4202 : tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6223 6943 : ? gimple_omp_parallel_clauses (inner_stmt)
6224 1461 : : gimple_omp_for_clauses (inner_stmt);
6225 4202 : tree innerc = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6226 4202 : gcc_assert (innerc);
6227 4202 : startvar = OMP_CLAUSE_DECL (innerc);
6228 4202 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
6229 : OMP_CLAUSE__LOOPTEMP_);
6230 4202 : gcc_assert (innerc);
6231 4202 : endvar = OMP_CLAUSE_DECL (innerc);
6232 1663 : if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
6233 5087 : && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6234 : {
6235 704 : innerc = find_lastprivate_looptemp (fd, innerc);
6236 704 : if (innerc)
6237 : {
6238 : /* If needed (distribute parallel for with lastprivate),
6239 : propagate down the total number of iterations. */
6240 320 : tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
6241 : fd->loop.n2);
6242 320 : t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
6243 : GSI_CONTINUE_LINKING);
6244 320 : assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
6245 320 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6246 : }
6247 : }
6248 : }
6249 :
6250 5855 : t = fold_convert (itype, s0);
6251 5855 : t = fold_build2 (MULT_EXPR, itype, t, step);
6252 5855 : if (POINTER_TYPE_P (type))
6253 : {
6254 316 : t = fold_build_pointer_plus (n1, t);
6255 380 : if (!POINTER_TYPE_P (TREE_TYPE (startvar))
6256 380 : && TYPE_PRECISION (TREE_TYPE (startvar)) > TYPE_PRECISION (type))
6257 0 : t = fold_convert (signed_type_for (type), t);
6258 : }
6259 : else
6260 5539 : t = fold_build2 (PLUS_EXPR, type, t, n1);
6261 5855 : t = fold_convert (TREE_TYPE (startvar), t);
6262 5855 : t = force_gimple_operand_gsi (&gsi, t,
6263 5855 : DECL_P (startvar)
6264 5843 : && TREE_ADDRESSABLE (startvar),
6265 : NULL_TREE, false, GSI_CONTINUE_LINKING);
6266 5855 : assign_stmt = gimple_build_assign (startvar, t);
6267 5855 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6268 5855 : if (cond_var)
6269 : {
6270 49 : tree itype = TREE_TYPE (cond_var);
6271 : /* For lastprivate(conditional:) itervar, we need some iteration
6272 : counter that starts at unsigned non-zero and increases.
6273 : Prefer as few IVs as possible, so if we can use startvar
6274 : itself, use that, or startvar + constant (those would be
6275 : incremented with step), and as last resort use the s0 + 1
6276 : incremented by 1. */
6277 49 : if (POINTER_TYPE_P (type)
6278 49 : || TREE_CODE (n1) != INTEGER_CST
6279 43 : || fd->loop.cond_code != LT_EXPR)
6280 6 : t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, s0),
6281 : build_int_cst (itype, 1));
6282 43 : else if (tree_int_cst_sgn (n1) == 1)
6283 21 : t = fold_convert (itype, t);
6284 : else
6285 : {
6286 22 : tree c = fold_convert (itype, n1);
6287 22 : c = fold_build2 (MINUS_EXPR, itype, build_int_cst (itype, 1), c);
6288 22 : t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, t), c);
6289 : }
6290 49 : t = force_gimple_operand_gsi (&gsi, t, false,
6291 : NULL_TREE, false, GSI_CONTINUE_LINKING);
6292 49 : assign_stmt = gimple_build_assign (cond_var, t);
6293 49 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6294 : }
6295 :
6296 5855 : t = fold_convert (itype, e0);
6297 5855 : t = fold_build2 (MULT_EXPR, itype, t, step);
6298 5855 : if (POINTER_TYPE_P (type))
6299 : {
6300 316 : t = fold_build_pointer_plus (n1, t);
6301 380 : if (!POINTER_TYPE_P (TREE_TYPE (startvar))
6302 380 : && TYPE_PRECISION (TREE_TYPE (startvar)) > TYPE_PRECISION (type))
6303 0 : t = fold_convert (signed_type_for (type), t);
6304 : }
6305 : else
6306 5539 : t = fold_build2 (PLUS_EXPR, type, t, n1);
6307 5855 : t = fold_convert (TREE_TYPE (startvar), t);
6308 5855 : e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6309 : false, GSI_CONTINUE_LINKING);
6310 5855 : if (endvar)
6311 : {
6312 4202 : assign_stmt = gimple_build_assign (endvar, e);
6313 4202 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6314 4202 : if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6315 3434 : assign_stmt = gimple_build_assign (fd->loop.v, e);
6316 : else
6317 768 : assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6318 4202 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6319 : }
6320 : /* Handle linear clause adjustments. */
6321 5855 : tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
6322 5855 : if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
6323 15866 : for (tree c = gimple_omp_for_clauses (fd->for_stmt);
6324 15866 : c; c = OMP_CLAUSE_CHAIN (c))
6325 13481 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
6326 13481 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
6327 : {
6328 68 : tree d = OMP_CLAUSE_DECL (c);
6329 68 : tree t = d, a, dest;
6330 68 : if (omp_privatize_by_reference (t))
6331 3 : t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
6332 68 : tree type = TREE_TYPE (t);
6333 68 : if (POINTER_TYPE_P (type))
6334 0 : type = sizetype;
6335 68 : dest = unshare_expr (t);
6336 68 : tree v = create_tmp_var (TREE_TYPE (t), NULL);
6337 68 : expand_omp_build_assign (&gsif, v, t);
6338 68 : if (itercnt == NULL_TREE)
6339 : {
6340 68 : if (gimple_omp_for_combined_into_p (fd->for_stmt))
6341 : {
6342 0 : itercntbias
6343 0 : = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
6344 : fold_convert (itype, fd->loop.n1));
6345 0 : itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
6346 : itercntbias, step);
6347 0 : itercntbias
6348 0 : = force_gimple_operand_gsi (&gsif, itercntbias, true,
6349 : NULL_TREE, true,
6350 : GSI_SAME_STMT);
6351 0 : itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
6352 0 : itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
6353 : NULL_TREE, false,
6354 : GSI_CONTINUE_LINKING);
6355 : }
6356 : else
6357 : itercnt = s0;
6358 : }
6359 68 : a = fold_build2 (MULT_EXPR, type,
6360 : fold_convert (type, itercnt),
6361 : fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
6362 68 : t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
6363 : : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
6364 68 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6365 : false, GSI_CONTINUE_LINKING);
6366 68 : expand_omp_build_assign (&gsi, dest, t, true);
6367 : }
6368 5855 : if (fd->collapse > 1)
6369 2232 : expand_omp_for_init_vars (fd, &gsi, counts, NULL, inner_stmt, startvar);
6370 :
6371 5855 : if (!broken_loop)
6372 : {
6373 : /* The code controlling the sequential loop goes in CONT_BB,
6374 : replacing the GIMPLE_OMP_CONTINUE. */
6375 5598 : gsi = gsi_last_nondebug_bb (cont_bb);
6376 5598 : gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6377 5598 : vmain = gimple_omp_continue_control_use (cont_stmt);
6378 5598 : vback = gimple_omp_continue_control_def (cont_stmt);
6379 :
6380 5598 : if (cond_var)
6381 : {
6382 49 : tree itype = TREE_TYPE (cond_var);
6383 49 : tree t2;
6384 49 : if (POINTER_TYPE_P (type)
6385 49 : || TREE_CODE (n1) != INTEGER_CST
6386 43 : || fd->loop.cond_code != LT_EXPR)
6387 6 : t2 = build_int_cst (itype, 1);
6388 : else
6389 43 : t2 = fold_convert (itype, step);
6390 49 : t2 = fold_build2 (PLUS_EXPR, itype, cond_var, t2);
6391 49 : t2 = force_gimple_operand_gsi (&gsi, t2, false,
6392 : NULL_TREE, true, GSI_SAME_STMT);
6393 49 : assign_stmt = gimple_build_assign (cond_var, t2);
6394 49 : gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6395 : }
6396 :
6397 5598 : if (!gimple_omp_for_combined_p (fd->for_stmt))
6398 : {
6399 1396 : if (POINTER_TYPE_P (type))
6400 96 : t = fold_build_pointer_plus (vmain, step);
6401 : else
6402 1300 : t = fold_build2 (PLUS_EXPR, type, vmain, step);
6403 1396 : t = force_gimple_operand_gsi (&gsi, t,
6404 1396 : DECL_P (vback)
6405 1384 : && TREE_ADDRESSABLE (vback), NULL_TREE,
6406 : true, GSI_SAME_STMT);
6407 1396 : assign_stmt = gimple_build_assign (vback, t);
6408 1396 : gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6409 :
6410 1396 : if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
6411 94 : t = build2 (EQ_EXPR, boolean_type_node,
6412 : build_int_cst (itype, 0),
6413 : build_int_cst (itype, 1));
6414 : else
6415 1302 : t = build2 (fd->loop.cond_code, boolean_type_node,
6416 1302 : DECL_P (vback) && TREE_ADDRESSABLE (vback)
6417 : ? t : vback, e);
6418 1396 : gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6419 : }
6420 :
6421 : /* Remove GIMPLE_OMP_CONTINUE. */
6422 5598 : gsi_remove (&gsi, true);
6423 :
6424 5598 : if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6425 449 : collapse_bb = extract_omp_for_update_vars (fd, NULL, cont_bb, body_bb);
6426 :
6427 : /* Trip update code goes into TRIP_UPDATE_BB. */
6428 5598 : gsi = gsi_start_bb (trip_update_bb);
6429 :
6430 5598 : t = build_int_cst (itype, 1);
6431 5598 : t = build2 (PLUS_EXPR, itype, trip_main, t);
6432 5598 : assign_stmt = gimple_build_assign (trip_back, t);
6433 5598 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6434 : }
6435 :
6436 5855 : gsi = gsi_last_nondebug_bb (exit_bb);
6437 5855 : if (flag_openmp_ompt && !has_gomp_loop_end)
6438 : {
6439 : /* Insert call to GOMP_*_static_worksharing_end at the end of exit_bb.
6440 : */
6441 16 : tree decl;
6442 16 : switch (gimple_omp_for_kind (fd->for_stmt))
6443 : {
6444 8 : case GF_OMP_FOR_KIND_FOR:
6445 8 : decl
6446 8 : = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_END);
6447 8 : break;
6448 8 : case GF_OMP_FOR_KIND_DISTRIBUTE:
6449 8 : decl = builtin_decl_explicit (
6450 : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_END);
6451 8 : break;
6452 0 : default:
6453 0 : gcc_unreachable ();
6454 : }
6455 16 : gcall *g = gimple_build_call (decl, 0);
6456 16 : gsi_insert_after (&gsi, g, GSI_SAME_STMT);
6457 : }
6458 :
6459 : /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6460 5855 : if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6461 : {
6462 320 : t = gimple_omp_return_lhs (gsi_stmt (gsi));
6463 320 : if (fd->have_reductemp || fd->have_pointer_condtemp)
6464 : {
6465 35 : tree fn;
6466 35 : if (t)
6467 0 : fn = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6468 : else
6469 35 : fn = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6470 35 : gcall *g = gimple_build_call (fn, 0);
6471 35 : if (t)
6472 : {
6473 0 : gimple_call_set_lhs (g, t);
6474 0 : if (fd->have_reductemp)
6475 0 : gsi_insert_after (&gsi, gimple_build_assign (reductions,
6476 : NOP_EXPR, t),
6477 : GSI_SAME_STMT);
6478 : }
6479 35 : gsi_insert_after (&gsi, g, GSI_SAME_STMT);
6480 35 : }
6481 : else
6482 285 : gsi_insert_after (&gsi,
6483 : omp_build_barrier (t,
6484 : GOMP_BARRIER_IMPLICIT_WORKSHARE),
6485 : GSI_SAME_STMT);
6486 : }
6487 5535 : else if (fd->have_pointer_condtemp)
6488 : {
6489 9 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6490 9 : gcall *g = gimple_build_call (fn, 0);
6491 9 : gsi_insert_after (&gsi, g, GSI_SAME_STMT);
6492 : }
6493 5855 : gsi_remove (&gsi, true);
6494 :
6495 5855 : if (flag_openmp_ompt == OMP_OMPT_LEVEL_EXTENDED)
6496 : {
6497 : /* Insert call to GOMP_*_static_worksharing_dispatch at the end of
6498 : seq_start_bb. */
6499 8 : gsi = gsi_last_nondebug_bb (seq_start_bb);
6500 8 : tree decl;
6501 8 : switch (gimple_omp_for_kind (fd->for_stmt))
6502 : {
6503 4 : case GF_OMP_FOR_KIND_FOR:
6504 4 : decl = builtin_decl_explicit (
6505 : BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_DISPATCH);
6506 4 : break;
6507 4 : case GF_OMP_FOR_KIND_DISTRIBUTE:
6508 4 : decl = builtin_decl_explicit (
6509 : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_DISPATCH);
6510 4 : break;
6511 0 : default:
6512 0 : gcc_unreachable ();
6513 : }
6514 8 : tree s0_ull = fold_convert (long_long_unsigned_type_node, s0);
6515 8 : tree iterations = fold_build2 (MINUS_EXPR, itype, e0, s0);
6516 8 : iterations = fold_convert (long_long_unsigned_type_node, iterations);
6517 8 : tree call = build_call_expr (decl, 2, s0_ull, iterations);
6518 8 : force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true,
6519 : GSI_SAME_STMT);
6520 : }
6521 :
6522 : /* Connect the new blocks. */
6523 5855 : find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6524 5855 : find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6525 :
6526 5855 : if (!broken_loop)
6527 : {
6528 5598 : se = find_edge (cont_bb, body_bb);
6529 5598 : if (se == NULL)
6530 : {
6531 12 : se = BRANCH_EDGE (cont_bb);
6532 12 : gcc_assert (single_succ (se->dest) == body_bb);
6533 : }
6534 5598 : if (gimple_omp_for_combined_p (fd->for_stmt))
6535 : {
6536 4202 : remove_edge (se);
6537 4202 : se = NULL;
6538 : }
6539 1396 : else if (fd->collapse > 1)
6540 : {
6541 449 : remove_edge (se);
6542 449 : se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6543 : }
6544 : else
6545 947 : se->flags = EDGE_TRUE_VALUE;
6546 9800 : find_edge (cont_bb, trip_update_bb)->flags
6547 449 : = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6548 :
6549 5598 : redirect_edge_and_branch (single_succ_edge (trip_update_bb),
6550 : iter_part_bb);
6551 : }
6552 :
6553 5855 : if (gimple_in_ssa_p (cfun))
6554 : {
6555 12 : gphi_iterator psi;
6556 12 : gphi *phi;
6557 12 : edge re, ene;
6558 12 : edge_var_map *vm;
6559 12 : size_t i;
6560 :
6561 12 : gcc_assert (fd->collapse == 1 && !broken_loop);
6562 :
6563 : /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6564 : remove arguments of the phi nodes in fin_bb. We need to create
6565 : appropriate phi nodes in iter_part_bb instead. */
6566 12 : se = find_edge (iter_part_bb, fin_bb);
6567 12 : re = single_succ_edge (trip_update_bb);
6568 12 : vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
6569 12 : ene = single_succ_edge (entry_bb);
6570 :
6571 12 : psi = gsi_start_phis (fin_bb);
6572 33 : for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6573 9 : gsi_next (&psi), ++i)
6574 : {
6575 9 : gphi *nphi;
6576 9 : location_t locus;
6577 :
6578 9 : phi = psi.phi ();
6579 9 : if (operand_equal_p (gimple_phi_arg_def (phi, 0),
6580 9 : redirect_edge_var_map_def (vm), 0))
6581 0 : continue;
6582 :
6583 9 : t = gimple_phi_result (phi);
6584 9 : gcc_assert (t == redirect_edge_var_map_result (vm));
6585 :
6586 9 : if (!single_pred_p (fin_bb))
6587 1 : t = copy_ssa_name (t, phi);
6588 :
6589 9 : nphi = create_phi_node (t, iter_part_bb);
6590 :
6591 9 : t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6592 9 : locus = gimple_phi_arg_location_from_edge (phi, se);
6593 :
6594 : /* A special case -- fd->loop.v is not yet computed in
6595 : iter_part_bb, we need to use vextra instead. */
6596 9 : if (t == fd->loop.v)
6597 0 : t = vextra;
6598 9 : add_phi_arg (nphi, t, ene, locus);
6599 9 : locus = redirect_edge_var_map_location (vm);
6600 9 : tree back_arg = redirect_edge_var_map_def (vm);
6601 9 : add_phi_arg (nphi, back_arg, re, locus);
6602 9 : edge ce = find_edge (cont_bb, body_bb);
6603 9 : if (ce == NULL)
6604 : {
6605 9 : ce = BRANCH_EDGE (cont_bb);
6606 9 : gcc_assert (single_succ (ce->dest) == body_bb);
6607 : ce = single_succ_edge (ce->dest);
6608 : }
6609 9 : gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
6610 9 : gcc_assert (inner_loop_phi != NULL);
6611 9 : add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
6612 : find_edge (seq_start_bb, body_bb), locus);
6613 :
6614 9 : if (!single_pred_p (fin_bb))
6615 1 : add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
6616 : }
6617 21 : gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
6618 12 : redirect_edge_var_map_clear (re);
6619 12 : if (single_pred_p (fin_bb))
6620 27 : while (1)
6621 : {
6622 19 : psi = gsi_start_phis (fin_bb);
6623 19 : if (gsi_end_p (psi))
6624 : break;
6625 8 : remove_phi_node (&psi, false);
6626 : }
6627 :
6628 : /* Make phi node for trip. */
6629 12 : phi = create_phi_node (trip_main, iter_part_bb);
6630 12 : add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6631 : UNKNOWN_LOCATION);
6632 12 : add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6633 : UNKNOWN_LOCATION);
6634 : }
6635 :
6636 5855 : if (!broken_loop)
6637 5598 : set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6638 5855 : set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6639 : recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6640 5855 : set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6641 : recompute_dominator (CDI_DOMINATORS, fin_bb));
6642 5855 : set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6643 : recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6644 5855 : set_immediate_dominator (CDI_DOMINATORS, body_bb,
6645 : recompute_dominator (CDI_DOMINATORS, body_bb));
6646 :
6647 5855 : if (!broken_loop)
6648 : {
6649 5598 : class loop *loop = body_bb->loop_father;
6650 5598 : class loop *trip_loop = alloc_loop ();
6651 5598 : trip_loop->header = iter_part_bb;
6652 5598 : trip_loop->latch = trip_update_bb;
6653 5598 : add_loop (trip_loop, iter_part_bb->loop_father);
6654 :
6655 5598 : if (loop != entry_bb->loop_father)
6656 : {
6657 12 : gcc_assert (loop->header == body_bb);
6658 12 : gcc_assert (loop->latch == region->cont
6659 : || single_pred (loop->latch) == region->cont);
6660 12 : trip_loop->inner = loop;
6661 12 : return;
6662 : }
6663 :
6664 5586 : if (!gimple_omp_for_combined_p (fd->for_stmt))
6665 : {
6666 1384 : loop = alloc_loop ();
6667 1384 : loop->header = body_bb;
6668 1384 : if (collapse_bb == NULL)
6669 935 : loop->latch = cont_bb;
6670 1384 : add_loop (loop, trip_loop);
6671 : }
6672 : }
6673 : }
6674 :
6675 : /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6676 : loop. Given parameters:
6677 :
6678 : for (V = N1; V cond N2; V += STEP) BODY;
6679 :
6680 : where COND is "<" or ">", we generate pseudocode
6681 :
6682 : V = N1;
6683 : goto L1;
6684 : L0:
6685 : BODY;
6686 : V += STEP;
6687 : L1:
6688 : if (V cond N2) goto L0; else goto L2;
6689 : L2:
6690 :
6691 : For collapsed loops, emit the outer loops as scalar
6692 : and only try to vectorize the innermost loop. */
6693 :
6694 : static void
6695 9374 : expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6696 : {
6697 9374 : tree type, t;
6698 9374 : basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6699 9374 : gimple_stmt_iterator gsi;
6700 9374 : gimple *stmt;
6701 9374 : gcond *cond_stmt;
6702 9374 : bool broken_loop = region->cont == NULL;
6703 9374 : edge e, ne;
6704 9374 : tree *counts = NULL;
6705 9374 : int i;
6706 9374 : int safelen_int = INT_MAX;
6707 9374 : bool dont_vectorize = false;
6708 9374 : tree safelen = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
6709 : OMP_CLAUSE_SAFELEN);
6710 9374 : tree simduid = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
6711 : OMP_CLAUSE__SIMDUID_);
6712 9374 : tree ifc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
6713 : OMP_CLAUSE_IF);
6714 9374 : tree simdlen = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
6715 : OMP_CLAUSE_SIMDLEN);
6716 9374 : tree condtemp = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
6717 : OMP_CLAUSE__CONDTEMP_);
6718 9374 : tree n1, n2;
6719 9451 : tree cond_var = condtemp ? OMP_CLAUSE_DECL (condtemp) : NULL_TREE;
6720 :
6721 9374 : if (safelen)
6722 : {
6723 5367 : poly_uint64 val;
6724 5367 : safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6725 5367 : if (!poly_int_tree_p (safelen, &val))
6726 : safelen_int = 0;
6727 : else
6728 5352 : safelen_int = MIN (constant_lower_bound (val), INT_MAX);
6729 5352 : if (safelen_int == 1)
6730 1805 : safelen_int = 0;
6731 : }
6732 759 : if ((ifc && integer_zerop (OMP_CLAUSE_IF_EXPR (ifc)))
6733 10009 : || (simdlen && integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (simdlen))))
6734 : {
6735 : safelen_int = 0;
6736 : dont_vectorize = true;
6737 : }
6738 9374 : type = TREE_TYPE (fd->loop.v);
6739 9374 : entry_bb = region->entry;
6740 9374 : cont_bb = region->cont;
6741 9374 : gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6742 9374 : gcc_assert (broken_loop
6743 : || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6744 9374 : l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6745 9374 : if (!broken_loop)
6746 : {
6747 8302 : gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6748 8302 : gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6749 8302 : l1_bb = split_block (cont_bb, last_nondebug_stmt (cont_bb))->dest;
6750 8302 : l2_bb = BRANCH_EDGE (entry_bb)->dest;
6751 : }
6752 : else
6753 : {
6754 1072 : BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6755 1072 : l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6756 1072 : l2_bb = single_succ (l1_bb);
6757 : }
6758 9374 : exit_bb = region->exit;
6759 9374 : l2_dom_bb = NULL;
6760 :
6761 9374 : gsi = gsi_last_nondebug_bb (entry_bb);
6762 :
6763 9374 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6764 : /* Not needed in SSA form right now. */
6765 9374 : gcc_assert (!gimple_in_ssa_p (cfun));
6766 9374 : if (fd->collapse > 1
6767 9374 : && (gimple_omp_for_combined_into_p (fd->for_stmt)
6768 496 : || broken_loop))
6769 : {
6770 2277 : int first_zero_iter = -1, dummy = -1;
6771 2277 : basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
6772 :
6773 2277 : counts = XALLOCAVEC (tree, fd->collapse);
6774 2277 : expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6775 : zero_iter_bb, first_zero_iter,
6776 : dummy_bb, dummy, l2_dom_bb);
6777 : }
6778 9374 : if (l2_dom_bb == NULL)
6779 9366 : l2_dom_bb = l1_bb;
6780 :
6781 9374 : n1 = fd->loop.n1;
6782 9374 : n2 = fd->loop.n2;
6783 9374 : if (gimple_omp_for_combined_into_p (fd->for_stmt))
6784 : {
6785 7023 : tree innerc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
6786 : OMP_CLAUSE__LOOPTEMP_);
6787 7023 : gcc_assert (innerc);
6788 7023 : n1 = OMP_CLAUSE_DECL (innerc);
6789 7023 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
6790 : OMP_CLAUSE__LOOPTEMP_);
6791 7023 : gcc_assert (innerc);
6792 7023 : n2 = OMP_CLAUSE_DECL (innerc);
6793 : }
6794 9374 : tree step = fd->loop.step;
6795 9374 : tree orig_step = step; /* May be different from step if is_simt. */
6796 :
6797 9374 : bool is_simt = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
6798 9374 : OMP_CLAUSE__SIMT_);
6799 9374 : if (is_simt)
6800 : {
6801 0 : cfun->curr_properties &= ~PROP_gimple_lomp_dev;
6802 0 : is_simt = safelen_int > 1;
6803 : }
6804 9374 : tree simt_lane = NULL_TREE, simt_maxlane = NULL_TREE;
6805 9374 : if (is_simt)
6806 : {
6807 0 : simt_lane = create_tmp_var (unsigned_type_node);
6808 0 : gimple *g = gimple_build_call_internal (IFN_GOMP_SIMT_LANE, 0);
6809 0 : gimple_call_set_lhs (g, simt_lane);
6810 0 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
6811 0 : tree offset = fold_build2 (MULT_EXPR, TREE_TYPE (step), step,
6812 : fold_convert (TREE_TYPE (step), simt_lane));
6813 0 : n1 = fold_convert (type, n1);
6814 0 : if (POINTER_TYPE_P (type))
6815 0 : n1 = fold_build_pointer_plus (n1, offset);
6816 : else
6817 0 : n1 = fold_build2 (PLUS_EXPR, type, n1, fold_convert (type, offset));
6818 :
6819 : /* Collapsed loops not handled for SIMT yet: limit to one lane only. */
6820 0 : if (fd->collapse > 1)
6821 0 : simt_maxlane = build_one_cst (unsigned_type_node);
6822 0 : else if (safelen_int < omp_max_simt_vf ())
6823 0 : simt_maxlane = build_int_cst (unsigned_type_node, safelen_int);
6824 0 : tree vf
6825 0 : = build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_GOMP_SIMT_VF,
6826 : unsigned_type_node, 0);
6827 0 : if (simt_maxlane)
6828 0 : vf = fold_build2 (MIN_EXPR, unsigned_type_node, vf, simt_maxlane);
6829 0 : vf = fold_convert (TREE_TYPE (step), vf);
6830 0 : step = fold_build2 (MULT_EXPR, TREE_TYPE (step), step, vf);
6831 : }
6832 :
6833 9374 : tree n2var = NULL_TREE;
6834 9374 : tree n2v = NULL_TREE;
6835 9374 : tree *nonrect_bounds = NULL;
6836 9374 : tree min_arg1 = NULL_TREE, min_arg2 = NULL_TREE;
6837 9374 : if (fd->collapse > 1)
6838 : {
6839 2753 : if (broken_loop || gimple_omp_for_combined_into_p (fd->for_stmt))
6840 : {
6841 2277 : if (fd->non_rect)
6842 : {
6843 99 : nonrect_bounds = XALLOCAVEC (tree, fd->last_nonrect + 1);
6844 99 : memset (nonrect_bounds, 0,
6845 : sizeof (tree) * (fd->last_nonrect + 1));
6846 : }
6847 2277 : expand_omp_build_assign (&gsi, fd->loop.v, fold_convert (type, n1));
6848 2277 : gcc_assert (entry_bb == gsi_bb (gsi));
6849 2277 : gcc_assert (fd->for_stmt == gsi_stmt (gsi));
6850 2277 : gsi_prev (&gsi);
6851 2277 : entry_bb = split_block (entry_bb, gsi_stmt (gsi))->dest;
6852 2277 : expand_omp_for_init_vars (fd, &gsi, counts, nonrect_bounds,
6853 : NULL, n1);
6854 2277 : gsi = gsi_for_stmt (fd->for_stmt);
6855 : }
6856 2753 : if (broken_loop)
6857 : ;
6858 2217 : else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6859 : {
6860 : /* Compute in n2var the limit for the first innermost loop,
6861 : i.e. fd->loop.v + MIN (n2 - fd->loop.v, cnt)
6862 : where cnt is how many iterations would the loop have if
6863 : all further iterations were assigned to the current task. */
6864 1741 : n2var = create_tmp_var (type);
6865 1741 : i = fd->collapse - 1;
6866 1741 : tree itype = TREE_TYPE (fd->loops[i].v);
6867 1741 : if (POINTER_TYPE_P (itype))
6868 266 : itype = signed_type_for (itype);
6869 1741 : t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
6870 2511 : ? -1 : 1));
6871 1741 : t = fold_build2 (PLUS_EXPR, itype,
6872 : fold_convert (itype, fd->loops[i].step), t);
6873 1741 : t = fold_build2 (PLUS_EXPR, itype, t,
6874 : fold_convert (itype, fd->loops[i].n2));
6875 1741 : if (fd->loops[i].m2)
6876 : {
6877 26 : tree t2 = fold_convert (itype,
6878 : fd->loops[i - fd->loops[i].outer].v);
6879 26 : tree t3 = fold_convert (itype, fd->loops[i].m2);
6880 26 : t2 = fold_build2 (MULT_EXPR, TREE_TYPE (t), t2, t3);
6881 26 : t = fold_build2 (PLUS_EXPR, itype, t, t2);
6882 : }
6883 1741 : t = fold_build2 (MINUS_EXPR, itype, t,
6884 : fold_convert (itype, fd->loops[i].v));
6885 1741 : if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
6886 256 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
6887 : fold_build1 (NEGATE_EXPR, itype, t),
6888 : fold_build1 (NEGATE_EXPR, itype,
6889 : fold_convert (itype,
6890 : fd->loops[i].step)));
6891 : else
6892 1485 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
6893 : fold_convert (itype, fd->loops[i].step));
6894 1741 : t = fold_convert (type, t);
6895 1741 : tree t2 = fold_build2 (MINUS_EXPR, type, n2, n1);
6896 1741 : min_arg1 = create_tmp_var (type);
6897 1741 : expand_omp_build_assign (&gsi, min_arg1, t2);
6898 1741 : min_arg2 = create_tmp_var (type);
6899 1741 : expand_omp_build_assign (&gsi, min_arg2, t);
6900 : }
6901 : else
6902 : {
6903 476 : if (TREE_CODE (n2) == INTEGER_CST)
6904 : {
6905 : /* Indicate for lastprivate handling that at least one iteration
6906 : has been performed, without wasting runtime. */
6907 138 : if (integer_nonzerop (n2))
6908 130 : expand_omp_build_assign (&gsi, fd->loop.v,
6909 : fold_convert (type, n2));
6910 : else
6911 : /* Indicate that no iteration has been performed. */
6912 8 : expand_omp_build_assign (&gsi, fd->loop.v,
6913 : build_one_cst (type));
6914 : }
6915 : else
6916 : {
6917 338 : expand_omp_build_assign (&gsi, fd->loop.v,
6918 : build_zero_cst (type));
6919 338 : expand_omp_build_assign (&gsi, n2, build_one_cst (type));
6920 : }
6921 476 : for (i = 0; i < fd->collapse; i++)
6922 : {
6923 476 : t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6924 476 : if (fd->loops[i].m1)
6925 : {
6926 0 : tree t2
6927 0 : = fold_convert (TREE_TYPE (t),
6928 : fd->loops[i - fd->loops[i].outer].v);
6929 0 : tree t3 = fold_convert (TREE_TYPE (t), fd->loops[i].m1);
6930 0 : t2 = fold_build2 (MULT_EXPR, TREE_TYPE (t), t2, t3);
6931 0 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t, t2);
6932 : }
6933 476 : expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6934 : /* For normal non-combined collapsed loops just initialize
6935 : the outermost iterator in the entry_bb. */
6936 476 : if (!broken_loop)
6937 : break;
6938 : }
6939 : }
6940 : }
6941 : else
6942 6621 : expand_omp_build_assign (&gsi, fd->loop.v, fold_convert (type, n1));
6943 9374 : tree altv = NULL_TREE, altn2 = NULL_TREE;
6944 9374 : if (fd->collapse == 1
6945 6621 : && !broken_loop
6946 6085 : && TREE_CODE (orig_step) != INTEGER_CST)
6947 : {
6948 : /* The vectorizer currently punts on loops with non-constant steps
6949 : for the main IV (can't compute number of iterations and gives up
6950 : because of that). As for OpenMP loops it is always possible to
6951 : compute the number of iterations upfront, use an alternate IV
6952 : as the loop iterator:
6953 : altn2 = n1 < n2 ? (n2 - n1 + step - 1) / step : 0;
6954 : for (i = n1, altv = 0; altv < altn2; altv++, i += step) */
6955 176 : altv = create_tmp_var (unsigned_type_for (TREE_TYPE (fd->loops[0].v)));
6956 176 : expand_omp_build_assign (&gsi, altv, build_zero_cst (TREE_TYPE (altv)));
6957 176 : tree itype = TREE_TYPE (fd->loop.v);
6958 176 : if (POINTER_TYPE_P (itype))
6959 0 : itype = signed_type_for (itype);
6960 334 : t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6961 176 : t = fold_build2 (PLUS_EXPR, itype,
6962 : fold_convert (itype, step), t);
6963 176 : t = fold_build2 (PLUS_EXPR, itype, t, fold_convert (itype, n2));
6964 176 : t = fold_build2 (MINUS_EXPR, itype, t,
6965 : fold_convert (itype, fd->loop.v));
6966 176 : if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6967 0 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
6968 : fold_build1 (NEGATE_EXPR, itype, t),
6969 : fold_build1 (NEGATE_EXPR, itype,
6970 : fold_convert (itype, step)));
6971 : else
6972 176 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
6973 : fold_convert (itype, step));
6974 176 : t = fold_convert (TREE_TYPE (altv), t);
6975 176 : altn2 = create_tmp_var (TREE_TYPE (altv));
6976 176 : expand_omp_build_assign (&gsi, altn2, t);
6977 176 : tree t2 = fold_convert (TREE_TYPE (fd->loop.v), n2);
6978 176 : t2 = fold_build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t2);
6979 176 : t2 = force_gimple_operand_gsi (&gsi, t2, true, NULL_TREE,
6980 : true, GSI_SAME_STMT);
6981 176 : gassign *g = gimple_build_assign (altn2, COND_EXPR, t2, altn2,
6982 176 : build_zero_cst (TREE_TYPE (altv)));
6983 176 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
6984 176 : }
6985 9198 : else if (fd->collapse > 1
6986 2753 : && !broken_loop
6987 2217 : && !gimple_omp_for_combined_into_p (fd->for_stmt)
6988 9674 : && TREE_CODE (fd->loops[fd->collapse - 1].step) != INTEGER_CST)
6989 : {
6990 22 : altv = create_tmp_var (unsigned_type_for (TREE_TYPE (fd->loops[0].v)));
6991 22 : altn2 = create_tmp_var (TREE_TYPE (altv));
6992 : }
6993 9374 : if (cond_var)
6994 : {
6995 77 : if (POINTER_TYPE_P (type)
6996 77 : || TREE_CODE (n1) != INTEGER_CST
6997 15 : || fd->loop.cond_code != LT_EXPR
6998 92 : || tree_int_cst_sgn (n1) != 1)
6999 72 : expand_omp_build_assign (&gsi, cond_var,
7000 72 : build_one_cst (TREE_TYPE (cond_var)));
7001 : else
7002 5 : expand_omp_build_assign (&gsi, cond_var,
7003 5 : fold_convert (TREE_TYPE (cond_var), n1));
7004 : }
7005 :
7006 : /* Remove the GIMPLE_OMP_FOR statement. */
7007 9374 : gsi_remove (&gsi, true);
7008 :
7009 9374 : if (!broken_loop)
7010 : {
7011 : /* Code to control the increment goes in the CONT_BB. */
7012 8302 : gsi = gsi_last_nondebug_bb (cont_bb);
7013 8302 : stmt = gsi_stmt (gsi);
7014 8302 : gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7015 :
7016 8302 : if (fd->collapse == 1
7017 8302 : || gimple_omp_for_combined_into_p (fd->for_stmt))
7018 : {
7019 7826 : if (POINTER_TYPE_P (type))
7020 286 : t = fold_build_pointer_plus (fd->loop.v, step);
7021 : else
7022 7540 : t = fold_build2 (PLUS_EXPR, type, fd->loop.v, step);
7023 7826 : expand_omp_build_assign (&gsi, fd->loop.v, t);
7024 : }
7025 476 : else if (TREE_CODE (n2) != INTEGER_CST)
7026 338 : expand_omp_build_assign (&gsi, fd->loop.v, build_one_cst (type));
7027 8302 : if (altv)
7028 : {
7029 198 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (altv), altv,
7030 : build_one_cst (TREE_TYPE (altv)));
7031 198 : expand_omp_build_assign (&gsi, altv, t);
7032 : }
7033 :
7034 8302 : if (fd->collapse > 1)
7035 : {
7036 2217 : i = fd->collapse - 1;
7037 2217 : if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7038 280 : t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7039 : else
7040 : {
7041 1937 : t = fold_convert (TREE_TYPE (fd->loops[i].v),
7042 : fd->loops[i].step);
7043 1937 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7044 : fd->loops[i].v, t);
7045 : }
7046 2217 : expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7047 : }
7048 8302 : if (cond_var)
7049 : {
7050 77 : if (POINTER_TYPE_P (type)
7051 77 : || TREE_CODE (n1) != INTEGER_CST
7052 15 : || fd->loop.cond_code != LT_EXPR
7053 92 : || tree_int_cst_sgn (n1) != 1)
7054 72 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (cond_var), cond_var,
7055 : build_one_cst (TREE_TYPE (cond_var)));
7056 : else
7057 5 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (cond_var), cond_var,
7058 : fold_convert (TREE_TYPE (cond_var), step));
7059 77 : expand_omp_build_assign (&gsi, cond_var, t);
7060 : }
7061 :
7062 : /* Remove GIMPLE_OMP_CONTINUE. */
7063 8302 : gsi_remove (&gsi, true);
7064 : }
7065 :
7066 : /* Emit the condition in L1_BB. */
7067 9374 : gsi = gsi_start_bb (l1_bb);
7068 :
7069 9374 : if (altv)
7070 198 : t = build2 (LT_EXPR, boolean_type_node, altv, altn2);
7071 9176 : else if (fd->collapse > 1
7072 2731 : && !gimple_omp_for_combined_into_p (fd->for_stmt)
7073 9650 : && !broken_loop)
7074 : {
7075 454 : i = fd->collapse - 1;
7076 454 : tree itype = TREE_TYPE (fd->loops[i].v);
7077 454 : if (fd->loops[i].m2)
7078 203 : t = n2v = create_tmp_var (itype);
7079 : else
7080 251 : t = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7081 454 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7082 : false, GSI_CONTINUE_LINKING);
7083 454 : tree v = fd->loops[i].v;
7084 454 : if (DECL_P (v) && TREE_ADDRESSABLE (v))
7085 0 : v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7086 : false, GSI_CONTINUE_LINKING);
7087 454 : t = build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7088 : }
7089 : else
7090 : {
7091 8722 : if (fd->collapse > 1 && !broken_loop)
7092 : t = n2var;
7093 : else
7094 6981 : t = fold_convert (type, unshare_expr (n2));
7095 8722 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7096 : false, GSI_CONTINUE_LINKING);
7097 8722 : tree v = fd->loop.v;
7098 8722 : if (DECL_P (v) && TREE_ADDRESSABLE (v))
7099 0 : v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7100 : false, GSI_CONTINUE_LINKING);
7101 8722 : t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
7102 : }
7103 9374 : cond_stmt = gimple_build_cond_empty (t);
7104 9374 : gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7105 9374 : if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7106 : NULL, NULL)
7107 9374 : || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7108 : NULL, NULL))
7109 : {
7110 0 : gsi = gsi_for_stmt (cond_stmt);
7111 0 : gimple_regimplify_operands (cond_stmt, &gsi);
7112 : }
7113 :
7114 : /* Add 'V -= STEP * (SIMT_VF - 1)' after the loop. */
7115 9374 : if (is_simt)
7116 : {
7117 0 : gsi = gsi_start_bb (l2_bb);
7118 0 : step = fold_build2 (MINUS_EXPR, TREE_TYPE (step), orig_step, step);
7119 0 : if (POINTER_TYPE_P (type))
7120 0 : t = fold_build_pointer_plus (fd->loop.v, step);
7121 : else
7122 0 : t = fold_build2 (PLUS_EXPR, type, fd->loop.v, step);
7123 0 : expand_omp_build_assign (&gsi, fd->loop.v, t);
7124 : }
7125 :
7126 : /* Remove GIMPLE_OMP_RETURN. */
7127 9374 : gsi = gsi_last_nondebug_bb (exit_bb);
7128 9374 : gsi_remove (&gsi, true);
7129 :
7130 : /* Connect the new blocks. */
7131 9374 : remove_edge (FALLTHRU_EDGE (entry_bb));
7132 :
7133 9374 : if (!broken_loop)
7134 : {
7135 8302 : remove_edge (BRANCH_EDGE (entry_bb));
7136 8302 : make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7137 :
7138 8302 : e = BRANCH_EDGE (l1_bb);
7139 8302 : ne = FALLTHRU_EDGE (l1_bb);
7140 8302 : e->flags = EDGE_TRUE_VALUE;
7141 : }
7142 : else
7143 : {
7144 1072 : single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7145 :
7146 1072 : ne = single_succ_edge (l1_bb);
7147 1072 : e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7148 :
7149 : }
7150 9374 : ne->flags = EDGE_FALSE_VALUE;
7151 9374 : e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
7152 9374 : ne->probability = e->probability.invert ();
7153 :
7154 9374 : set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7155 9374 : set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7156 :
7157 9374 : if (simt_maxlane)
7158 : {
7159 0 : cond_stmt = gimple_build_cond (LT_EXPR, simt_lane, simt_maxlane,
7160 : NULL_TREE, NULL_TREE);
7161 0 : gsi = gsi_last_bb (entry_bb);
7162 0 : gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
7163 0 : make_edge (entry_bb, l2_bb, EDGE_FALSE_VALUE);
7164 0 : FALLTHRU_EDGE (entry_bb)->flags = EDGE_TRUE_VALUE;
7165 0 : FALLTHRU_EDGE (entry_bb)->probability
7166 0 : = profile_probability::guessed_always ().apply_scale (7, 8);
7167 0 : BRANCH_EDGE (entry_bb)->probability
7168 0 : = FALLTHRU_EDGE (entry_bb)->probability.invert ();
7169 0 : l2_dom_bb = entry_bb;
7170 : }
7171 9374 : set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7172 :
7173 9374 : if (!broken_loop && fd->collapse > 1)
7174 : {
7175 2217 : basic_block last_bb = l1_bb;
7176 2217 : basic_block init_bb = NULL;
7177 6108 : for (i = fd->collapse - 2; i >= 0; i--)
7178 : {
7179 3891 : tree nextn2v = NULL_TREE;
7180 3891 : if (EDGE_SUCC (last_bb, 0)->flags & EDGE_FALSE_VALUE)
7181 : e = EDGE_SUCC (last_bb, 0);
7182 : else
7183 2217 : e = EDGE_SUCC (last_bb, 1);
7184 3891 : basic_block bb = split_edge (e);
7185 3891 : if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7186 553 : t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7187 : else
7188 : {
7189 3338 : t = fold_convert (TREE_TYPE (fd->loops[i].v),
7190 : fd->loops[i].step);
7191 3338 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7192 : fd->loops[i].v, t);
7193 : }
7194 3891 : gsi = gsi_after_labels (bb);
7195 3891 : expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7196 :
7197 3891 : bb = split_block (bb, last_nondebug_stmt (bb))->dest;
7198 3891 : gsi = gsi_start_bb (bb);
7199 3891 : tree itype = TREE_TYPE (fd->loops[i].v);
7200 3891 : if (fd->loops[i].m2)
7201 0 : t = nextn2v = create_tmp_var (itype);
7202 : else
7203 3891 : t = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7204 3891 : t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7205 : false, GSI_CONTINUE_LINKING);
7206 3891 : tree v = fd->loops[i].v;
7207 3891 : if (DECL_P (v) && TREE_ADDRESSABLE (v))
7208 0 : v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7209 : false, GSI_CONTINUE_LINKING);
7210 3891 : t = build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7211 3891 : cond_stmt = gimple_build_cond_empty (t);
7212 3891 : gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7213 3891 : if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7214 : expand_omp_regimplify_p, NULL, NULL)
7215 3891 : || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7216 : expand_omp_regimplify_p, NULL, NULL))
7217 : {
7218 6 : gsi = gsi_for_stmt (cond_stmt);
7219 6 : gimple_regimplify_operands (cond_stmt, &gsi);
7220 : }
7221 3891 : ne = single_succ_edge (bb);
7222 3891 : ne->flags = EDGE_FALSE_VALUE;
7223 :
7224 3891 : init_bb = create_empty_bb (bb);
7225 3891 : set_immediate_dominator (CDI_DOMINATORS, init_bb, bb);
7226 3891 : add_bb_to_loop (init_bb, bb->loop_father);
7227 3891 : e = make_edge (bb, init_bb, EDGE_TRUE_VALUE);
7228 3891 : e->probability
7229 3891 : = profile_probability::guessed_always ().apply_scale (7, 8);
7230 3891 : ne->probability = e->probability.invert ();
7231 :
7232 3891 : gsi = gsi_after_labels (init_bb);
7233 3891 : if (fd->loops[i + 1].m1)
7234 : {
7235 242 : tree t2 = fold_convert (TREE_TYPE (fd->loops[i + 1].v),
7236 : fd->loops[i + 1
7237 : - fd->loops[i + 1].outer].v);
7238 242 : if (POINTER_TYPE_P (TREE_TYPE (t2)))
7239 6 : t = fold_build_pointer_plus (t2, fd->loops[i + 1].n1);
7240 : else
7241 : {
7242 236 : t = fold_convert (TREE_TYPE (fd->loops[i + 1].v),
7243 : fd->loops[i + 1].n1);
7244 236 : tree t3 = fold_convert (TREE_TYPE (t), fd->loops[i + 1].m1);
7245 236 : t2 = fold_build2 (MULT_EXPR, TREE_TYPE (t), t2, t3);
7246 236 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t, t2);
7247 : }
7248 : }
7249 : else
7250 3649 : t = fold_convert (TREE_TYPE (fd->loops[i + 1].v),
7251 : fd->loops[i + 1].n1);
7252 3891 : expand_omp_build_assign (&gsi, fd->loops[i + 1].v, t);
7253 3891 : if (fd->loops[i + 1].m2)
7254 : {
7255 241 : if (i + 2 == fd->collapse && (n2var || altv))
7256 : {
7257 38 : gcc_assert (n2v == NULL_TREE);
7258 38 : n2v = create_tmp_var (TREE_TYPE (fd->loops[i + 1].v));
7259 : }
7260 241 : tree t2 = fold_convert (TREE_TYPE (fd->loops[i + 1].v),
7261 : fd->loops[i + 1
7262 : - fd->loops[i + 1].outer].v);
7263 241 : if (POINTER_TYPE_P (TREE_TYPE (t2)))
7264 6 : t = fold_build_pointer_plus (t2, fd->loops[i + 1].n2);
7265 : else
7266 : {
7267 235 : t = fold_convert (TREE_TYPE (fd->loops[i + 1].v),
7268 : fd->loops[i + 1].n2);
7269 235 : tree t3 = fold_convert (TREE_TYPE (t), fd->loops[i + 1].m2);
7270 235 : t2 = fold_build2 (MULT_EXPR, TREE_TYPE (t), t2, t3);
7271 235 : t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t, t2);
7272 : }
7273 241 : expand_omp_build_assign (&gsi, n2v, t);
7274 : }
7275 3891 : if (i + 2 == fd->collapse && n2var)
7276 : {
7277 : /* For composite simd, n2 is the first iteration the current
7278 : task shouldn't already handle, so we effectively want to use
7279 : for (V3 = N31; V < N2 && V3 < N32; V++, V3 += STEP3)
7280 : as the vectorized loop. Except the vectorizer will not
7281 : vectorize that, so instead compute N2VAR as
7282 : N2VAR = V + MIN (N2 - V, COUNTS3) and use
7283 : for (V3 = N31; V < N2VAR; V++, V3 += STEP3)
7284 : as the loop to vectorize. */
7285 1741 : tree t2 = fold_build2 (MINUS_EXPR, type, n2, fd->loop.v);
7286 1741 : if (fd->loops[i + 1].m1 || fd->loops[i + 1].m2)
7287 : {
7288 99 : tree itype = TREE_TYPE (fd->loops[i].v);
7289 99 : if (POINTER_TYPE_P (itype))
7290 4 : itype = signed_type_for (itype);
7291 99 : t = build_int_cst (itype, (fd->loops[i + 1].cond_code
7292 99 : == LT_EXPR ? -1 : 1));
7293 99 : t = fold_build2 (PLUS_EXPR, itype,
7294 : fold_convert (itype,
7295 : fd->loops[i + 1].step), t);
7296 99 : if (fd->loops[i + 1].m2 == NULL_TREE)
7297 73 : t = fold_build2 (PLUS_EXPR, itype, t,
7298 : fold_convert (itype,
7299 : fd->loops[i + 1].n2));
7300 26 : else if (POINTER_TYPE_P (TREE_TYPE (n2v)))
7301 : {
7302 4 : t = fold_build_pointer_plus (n2v, t);
7303 4 : t = fold_convert (itype, t);
7304 : }
7305 : else
7306 22 : t = fold_build2 (PLUS_EXPR, itype, t, n2v);
7307 99 : t = fold_build2 (MINUS_EXPR, itype, t,
7308 : fold_convert (itype, fd->loops[i + 1].v));
7309 99 : tree step = fold_convert (itype, fd->loops[i + 1].step);
7310 99 : if (TYPE_UNSIGNED (itype)
7311 99 : && fd->loops[i + 1].cond_code == GT_EXPR)
7312 0 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
7313 : fold_build1 (NEGATE_EXPR, itype, t),
7314 : fold_build1 (NEGATE_EXPR, itype, step));
7315 : else
7316 99 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7317 99 : t = fold_convert (type, t);
7318 99 : }
7319 : else
7320 1642 : t = counts[i + 1];
7321 1741 : expand_omp_build_assign (&gsi, min_arg1, t2);
7322 1741 : expand_omp_build_assign (&gsi, min_arg2, t);
7323 1741 : e = split_block (init_bb, last_nondebug_stmt (init_bb));
7324 1741 : gsi = gsi_after_labels (e->dest);
7325 1741 : init_bb = e->dest;
7326 1741 : remove_edge (FALLTHRU_EDGE (entry_bb));
7327 1741 : make_edge (entry_bb, init_bb, EDGE_FALLTHRU);
7328 1741 : set_immediate_dominator (CDI_DOMINATORS, init_bb, entry_bb);
7329 1741 : set_immediate_dominator (CDI_DOMINATORS, l1_bb, init_bb);
7330 1741 : t = fold_build2 (MIN_EXPR, type, min_arg1, min_arg2);
7331 1741 : t = fold_build2 (PLUS_EXPR, type, fd->loop.v, t);
7332 1741 : expand_omp_build_assign (&gsi, n2var, t);
7333 : }
7334 3891 : if (i + 2 == fd->collapse && altv)
7335 : {
7336 : /* The vectorizer currently punts on loops with non-constant
7337 : steps for the main IV (can't compute number of iterations
7338 : and gives up because of that). As for OpenMP loops it is
7339 : always possible to compute the number of iterations upfront,
7340 : use an alternate IV as the loop iterator. */
7341 22 : expand_omp_build_assign (&gsi, altv,
7342 22 : build_zero_cst (TREE_TYPE (altv)));
7343 22 : tree itype = TREE_TYPE (fd->loops[i + 1].v);
7344 22 : if (POINTER_TYPE_P (itype))
7345 0 : itype = signed_type_for (itype);
7346 22 : t = build_int_cst (itype, (fd->loops[i + 1].cond_code == LT_EXPR
7347 26 : ? -1 : 1));
7348 22 : t = fold_build2 (PLUS_EXPR, itype,
7349 : fold_convert (itype, fd->loops[i + 1].step), t);
7350 22 : t = fold_build2 (PLUS_EXPR, itype, t,
7351 : fold_convert (itype,
7352 : fd->loops[i + 1].m2
7353 : ? n2v : fd->loops[i + 1].n2));
7354 22 : t = fold_build2 (MINUS_EXPR, itype, t,
7355 : fold_convert (itype, fd->loops[i + 1].v));
7356 22 : tree step = fold_convert (itype, fd->loops[i + 1].step);
7357 22 : if (TYPE_UNSIGNED (itype)
7358 22 : && fd->loops[i + 1].cond_code == GT_EXPR)
7359 0 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
7360 : fold_build1 (NEGATE_EXPR, itype, t),
7361 : fold_build1 (NEGATE_EXPR, itype, step));
7362 : else
7363 22 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7364 22 : t = fold_convert (TREE_TYPE (altv), t);
7365 22 : expand_omp_build_assign (&gsi, altn2, t);
7366 22 : tree t2 = fold_convert (TREE_TYPE (fd->loops[i + 1].v),
7367 : fd->loops[i + 1].m2
7368 : ? n2v : fd->loops[i + 1].n2);
7369 22 : t2 = fold_build2 (fd->loops[i + 1].cond_code, boolean_type_node,
7370 : fd->loops[i + 1].v, t2);
7371 22 : t2 = force_gimple_operand_gsi (&gsi, t2, true, NULL_TREE,
7372 : true, GSI_SAME_STMT);
7373 22 : gassign *g
7374 22 : = gimple_build_assign (altn2, COND_EXPR, t2, altn2,
7375 22 : build_zero_cst (TREE_TYPE (altv)));
7376 22 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
7377 : }
7378 3891 : n2v = nextn2v;
7379 :
7380 3891 : make_edge (init_bb, last_bb, EDGE_FALLTHRU);
7381 3891 : if (!gimple_omp_for_combined_into_p (fd->for_stmt))
7382 : {
7383 787 : e = find_edge (entry_bb, last_bb);
7384 787 : redirect_edge_succ (e, bb);
7385 787 : set_immediate_dominator (CDI_DOMINATORS, bb, entry_bb);
7386 787 : set_immediate_dominator (CDI_DOMINATORS, last_bb, init_bb);
7387 : }
7388 :
7389 3891 : last_bb = bb;
7390 : }
7391 : }
7392 8302 : if (!broken_loop)
7393 : {
7394 8302 : class loop *loop = alloc_loop ();
7395 8302 : loop->header = l1_bb;
7396 8302 : loop->latch = cont_bb;
7397 8302 : add_loop (loop, l1_bb->loop_father);
7398 8302 : loop->safelen = safelen_int;
7399 8302 : if (simduid)
7400 : {
7401 3473 : loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7402 3473 : cfun->has_simduid_loops = true;
7403 : }
7404 : /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7405 : the loop. */
7406 8302 : if ((flag_tree_loop_vectorize
7407 3316 : || !OPTION_SET_P (flag_tree_loop_vectorize))
7408 8302 : && flag_tree_loop_optimize
7409 8301 : && loop->safelen > 1)
7410 : {
7411 6498 : loop->force_vectorize = true;
7412 6498 : if (simdlen && tree_fits_uhwi_p (OMP_CLAUSE_SIMDLEN_EXPR (simdlen)))
7413 : {
7414 60 : unsigned HOST_WIDE_INT v
7415 60 : = tree_to_uhwi (OMP_CLAUSE_SIMDLEN_EXPR (simdlen));
7416 60 : if (v < INT_MAX && v <= (unsigned HOST_WIDE_INT) loop->safelen)
7417 60 : loop->simdlen = v;
7418 : }
7419 6498 : cfun->has_force_vectorize_loops = true;
7420 6498 : }
7421 1804 : else if (dont_vectorize)
7422 234 : loop->dont_vectorize = true;
7423 : }
7424 1072 : else if (simduid)
7425 530 : cfun->has_simduid_loops = true;
7426 9374 : }
7427 :
7428 : /* Taskloop construct is represented after gimplification with
7429 : two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
7430 : in between them. This routine expands the outer GIMPLE_OMP_FOR,
7431 : which should just compute all the needed loop temporaries
7432 : for GIMPLE_OMP_TASK. */
7433 :
7434 : static void
7435 1330 : expand_omp_taskloop_for_outer (struct omp_region *region,
7436 : struct omp_for_data *fd,
7437 : gimple *inner_stmt)
7438 : {
7439 1330 : tree type, bias = NULL_TREE;
7440 1330 : basic_block entry_bb, cont_bb, exit_bb;
7441 1330 : gimple_stmt_iterator gsi;
7442 1330 : gassign *assign_stmt;
7443 1330 : tree *counts = NULL;
7444 1330 : int i;
7445 :
7446 1330 : gcc_assert (inner_stmt);
7447 1330 : gcc_assert (region->cont);
7448 1330 : gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
7449 : && gimple_omp_task_taskloop_p (inner_stmt));
7450 1330 : type = TREE_TYPE (fd->loop.v);
7451 :
7452 : /* See if we need to bias by LLONG_MIN. */
7453 1330 : if (fd->iter_type == long_long_unsigned_type_node
7454 42 : && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == BITINT_TYPE)
7455 1358 : && !TYPE_UNSIGNED (type))
7456 : {
7457 0 : tree n1, n2;
7458 :
7459 0 : if (fd->loop.cond_code == LT_EXPR)
7460 : {
7461 0 : n1 = fd->loop.n1;
7462 0 : n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
7463 : }
7464 : else
7465 : {
7466 0 : n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
7467 0 : n2 = fd->loop.n1;
7468 : }
7469 0 : if (TREE_CODE (n1) != INTEGER_CST
7470 0 : || TREE_CODE (n2) != INTEGER_CST
7471 0 : || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
7472 0 : bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
7473 : }
7474 :
7475 1330 : entry_bb = region->entry;
7476 1330 : cont_bb = region->cont;
7477 1330 : gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7478 1330 : gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7479 1330 : exit_bb = region->exit;
7480 :
7481 1330 : gsi = gsi_last_nondebug_bb (entry_bb);
7482 1330 : gimple *for_stmt = gsi_stmt (gsi);
7483 1330 : gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
7484 1330 : if (fd->collapse > 1)
7485 : {
7486 181 : int first_zero_iter = -1, dummy = -1;
7487 181 : basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
7488 :
7489 181 : counts = XALLOCAVEC (tree, fd->collapse);
7490 181 : expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7491 : zero_iter_bb, first_zero_iter,
7492 : dummy_bb, dummy, l2_dom_bb);
7493 :
7494 181 : if (zero_iter_bb)
7495 : {
7496 : /* Some counts[i] vars might be uninitialized if
7497 : some loop has zero iterations. But the body shouldn't
7498 : be executed in that case, so just avoid uninit warnings. */
7499 336 : for (i = first_zero_iter; i < fd->collapse; i++)
7500 239 : if (SSA_VAR_P (counts[i]))
7501 226 : suppress_warning (counts[i], OPT_Wuninitialized);
7502 97 : gsi_prev (&gsi);
7503 97 : edge e = split_block (entry_bb, gsi_stmt (gsi));
7504 97 : entry_bb = e->dest;
7505 97 : make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
7506 97 : gsi = gsi_last_bb (entry_bb);
7507 97 : set_immediate_dominator (CDI_DOMINATORS, entry_bb,
7508 : get_immediate_dominator (CDI_DOMINATORS,
7509 : zero_iter_bb));
7510 : }
7511 : }
7512 :
7513 1330 : tree t0, t1;
7514 1330 : t1 = fd->loop.n2;
7515 1330 : t0 = fd->loop.n1;
7516 2646 : if (POINTER_TYPE_P (TREE_TYPE (t0))
7517 1330 : && TYPE_PRECISION (TREE_TYPE (t0))
7518 14 : != TYPE_PRECISION (fd->iter_type))
7519 : {
7520 : /* Avoid casting pointers to integer of a different size. */
7521 0 : tree itype = signed_type_for (type);
7522 0 : t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
7523 0 : t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
7524 : }
7525 : else
7526 : {
7527 1330 : t1 = fold_convert (fd->iter_type, t1);
7528 1330 : t0 = fold_convert (fd->iter_type, t0);
7529 : }
7530 1330 : if (bias)
7531 : {
7532 0 : t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
7533 0 : t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
7534 : }
7535 :
7536 1330 : tree innerc = omp_find_clause (gimple_omp_task_clauses (inner_stmt),
7537 : OMP_CLAUSE__LOOPTEMP_);
7538 1330 : gcc_assert (innerc);
7539 1330 : tree startvar = OMP_CLAUSE_DECL (innerc);
7540 1330 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
7541 1330 : gcc_assert (innerc);
7542 1330 : tree endvar = OMP_CLAUSE_DECL (innerc);
7543 1330 : if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7544 : {
7545 101 : innerc = find_lastprivate_looptemp (fd, innerc);
7546 101 : if (innerc)
7547 : {
7548 : /* If needed (inner taskloop has lastprivate clause), propagate
7549 : down the total number of iterations. */
7550 31 : tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
7551 : NULL_TREE, false,
7552 : GSI_CONTINUE_LINKING);
7553 31 : assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
7554 31 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7555 : }
7556 : }
7557 :
7558 1330 : t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
7559 : GSI_CONTINUE_LINKING);
7560 1330 : assign_stmt = gimple_build_assign (startvar, t0);
7561 1330 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7562 :
7563 1330 : t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
7564 : GSI_CONTINUE_LINKING);
7565 1330 : assign_stmt = gimple_build_assign (endvar, t1);
7566 1330 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7567 1330 : if (fd->collapse > 1)
7568 181 : expand_omp_for_init_vars (fd, &gsi, counts, NULL, inner_stmt, startvar);
7569 :
7570 : /* Remove the GIMPLE_OMP_FOR statement. */
7571 1330 : gsi = gsi_for_stmt (for_stmt);
7572 1330 : gsi_remove (&gsi, true);
7573 :
7574 1330 : gsi = gsi_last_nondebug_bb (cont_bb);
7575 1330 : gsi_remove (&gsi, true);
7576 :
7577 1330 : gsi = gsi_last_nondebug_bb (exit_bb);
7578 1330 : gsi_remove (&gsi, true);
7579 :
7580 1330 : FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
7581 1330 : remove_edge (BRANCH_EDGE (entry_bb));
7582 1330 : FALLTHRU_EDGE (cont_bb)->probability = profile_probability::always ();
7583 1330 : remove_edge (BRANCH_EDGE (cont_bb));
7584 1330 : set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
7585 1330 : set_immediate_dominator (CDI_DOMINATORS, region->entry,
7586 : recompute_dominator (CDI_DOMINATORS, region->entry));
7587 1330 : }
7588 :
7589 : /* Taskloop construct is represented after gimplification with
7590 : two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
7591 : in between them. This routine expands the inner GIMPLE_OMP_FOR.
7592 : GOMP_taskloop{,_ull} function arranges for each task to be given just
7593 : a single range of iterations. */
7594 :
7595 : static void
7596 1330 : expand_omp_taskloop_for_inner (struct omp_region *region,
7597 : struct omp_for_data *fd,
7598 : gimple *inner_stmt)
7599 : {
7600 1330 : tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
7601 1330 : basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
7602 1330 : basic_block fin_bb;
7603 1330 : gimple_stmt_iterator gsi;
7604 1330 : edge ep;
7605 1330 : bool broken_loop = region->cont == NULL;
7606 1330 : tree *counts = NULL;
7607 1330 : tree n1, n2, step;
7608 :
7609 1330 : itype = type = TREE_TYPE (fd->loop.v);
7610 1330 : if (POINTER_TYPE_P (type))
7611 14 : itype = signed_type_for (type);
7612 :
7613 : /* See if we need to bias by LLONG_MIN. */
7614 1330 : if (fd->iter_type == long_long_unsigned_type_node
7615 42 : && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == BITINT_TYPE)
7616 1358 : && !TYPE_UNSIGNED (type))
7617 : {
7618 0 : tree n1, n2;
7619 :
7620 0 : if (fd->loop.cond_code == LT_EXPR)
7621 : {
7622 0 : n1 = fd->loop.n1;
7623 0 : n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
7624 : }
7625 : else
7626 : {
7627 0 : n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
7628 0 : n2 = fd->loop.n1;
7629 : }
7630 0 : if (TREE_CODE (n1) != INTEGER_CST
7631 0 : || TREE_CODE (n2) != INTEGER_CST
7632 0 : || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
7633 0 : bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
7634 : }
7635 :
7636 1330 : entry_bb = region->entry;
7637 1330 : cont_bb = region->cont;
7638 1330 : gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7639 1330 : fin_bb = BRANCH_EDGE (entry_bb)->dest;
7640 1330 : gcc_assert (broken_loop
7641 : || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
7642 1330 : body_bb = FALLTHRU_EDGE (entry_bb)->dest;
7643 1330 : if (!broken_loop)
7644 : {
7645 1314 : gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
7646 1314 : gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7647 : }
7648 1330 : exit_bb = region->exit;
7649 :
7650 : /* Iteration space partitioning goes in ENTRY_BB. */
7651 1330 : gsi = gsi_last_nondebug_bb (entry_bb);
7652 1330 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7653 :
7654 1330 : if (fd->collapse > 1)
7655 : {
7656 181 : int first_zero_iter = -1, dummy = -1;
7657 181 : basic_block l2_dom_bb = NULL, dummy_bb = NULL;
7658 :
7659 181 : counts = XALLOCAVEC (tree, fd->collapse);
7660 181 : expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7661 : fin_bb, first_zero_iter,
7662 : dummy_bb, dummy, l2_dom_bb);
7663 181 : t = NULL_TREE;
7664 : }
7665 : else
7666 1330 : t = integer_one_node;
7667 :
7668 1330 : step = fd->loop.step;
7669 1330 : tree innerc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
7670 : OMP_CLAUSE__LOOPTEMP_);
7671 1330 : gcc_assert (innerc);
7672 1330 : n1 = OMP_CLAUSE_DECL (innerc);
7673 1330 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
7674 1330 : gcc_assert (innerc);
7675 1330 : n2 = OMP_CLAUSE_DECL (innerc);
7676 1330 : if (bias)
7677 : {
7678 0 : n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
7679 0 : n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
7680 : }
7681 1330 : n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7682 : true, NULL_TREE, true, GSI_SAME_STMT);
7683 1330 : n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7684 : true, NULL_TREE, true, GSI_SAME_STMT);
7685 1330 : step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7686 : true, NULL_TREE, true, GSI_SAME_STMT);
7687 :
7688 1330 : tree startvar = fd->loop.v;
7689 1330 : tree endvar = NULL_TREE;
7690 :
7691 1330 : if (gimple_omp_for_combined_p (fd->for_stmt))
7692 : {
7693 617 : tree clauses = gimple_omp_for_clauses (inner_stmt);
7694 617 : tree innerc = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7695 617 : gcc_assert (innerc);
7696 617 : startvar = OMP_CLAUSE_DECL (innerc);
7697 617 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
7698 : OMP_CLAUSE__LOOPTEMP_);
7699 617 : gcc_assert (innerc);
7700 617 : endvar = OMP_CLAUSE_DECL (innerc);
7701 : }
7702 1330 : t = fold_convert (TREE_TYPE (startvar), n1);
7703 1330 : t = force_gimple_operand_gsi (&gsi, t,
7704 1330 : DECL_P (startvar)
7705 1330 : && TREE_ADDRESSABLE (startvar),
7706 : NULL_TREE, false, GSI_CONTINUE_LINKING);
7707 1330 : gimple *assign_stmt = gimple_build_assign (startvar, t);
7708 1330 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7709 :
7710 1330 : t = fold_convert (TREE_TYPE (startvar), n2);
7711 1330 : e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7712 : false, GSI_CONTINUE_LINKING);
7713 1330 : if (endvar)
7714 : {
7715 617 : assign_stmt = gimple_build_assign (endvar, e);
7716 617 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7717 617 : if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7718 529 : assign_stmt = gimple_build_assign (fd->loop.v, e);
7719 : else
7720 88 : assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7721 617 : gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7722 : }
7723 :
7724 1330 : tree *nonrect_bounds = NULL;
7725 1330 : if (fd->collapse > 1)
7726 : {
7727 181 : if (fd->non_rect)
7728 : {
7729 19 : nonrect_bounds = XALLOCAVEC (tree, fd->last_nonrect + 1);
7730 19 : memset (nonrect_bounds, 0, sizeof (tree) * (fd->last_nonrect + 1));
7731 : }
7732 181 : gcc_assert (gsi_bb (gsi) == entry_bb);
7733 181 : expand_omp_for_init_vars (fd, &gsi, counts, nonrect_bounds, inner_stmt,
7734 : startvar);
7735 181 : entry_bb = gsi_bb (gsi);
7736 : }
7737 :
7738 1330 : if (!broken_loop)
7739 : {
7740 : /* The code controlling the sequential loop replaces the
7741 : GIMPLE_OMP_CONTINUE. */
7742 1314 : gsi = gsi_last_nondebug_bb (cont_bb);
7743 1314 : gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7744 1314 : gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
7745 1314 : vmain = gimple_omp_continue_control_use (cont_stmt);
7746 1314 : vback = gimple_omp_continue_control_def (cont_stmt);
7747 :
7748 1314 : if (!gimple_omp_for_combined_p (fd->for_stmt))
7749 : {
7750 697 : if (POINTER_TYPE_P (type))
7751 8 : t = fold_build_pointer_plus (vmain, step);
7752 : else
7753 689 : t = fold_build2 (PLUS_EXPR, type, vmain, step);
7754 697 : t = force_gimple_operand_gsi (&gsi, t,
7755 697 : DECL_P (vback)
7756 697 : && TREE_ADDRESSABLE (vback),
7757 : NULL_TREE, true, GSI_SAME_STMT);
7758 697 : assign_stmt = gimple_build_assign (vback, t);
7759 697 : gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7760 :
7761 697 : t = build2 (fd->loop.cond_code, boolean_type_node,
7762 697 : DECL_P (vback) && TREE_ADDRESSABLE (vback)
7763 : ? t : vback, e);
7764 697 : gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7765 : }
7766 :
7767 : /* Remove the GIMPLE_OMP_CONTINUE statement. */
7768 1314 : gsi_remove (&gsi, true);
7769 :
7770 1314 : if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7771 81 : collapse_bb = extract_omp_for_update_vars (fd, nonrect_bounds,
7772 : cont_bb, body_bb);
7773 : }
7774 :
7775 : /* Remove the GIMPLE_OMP_FOR statement. */
7776 1330 : gsi = gsi_for_stmt (fd->for_stmt);
7777 1330 : gsi_remove (&gsi, true);
7778 :
7779 : /* Remove the GIMPLE_OMP_RETURN statement. */
7780 1330 : gsi = gsi_last_nondebug_bb (exit_bb);
7781 1330 : gsi_remove (&gsi, true);
7782 :
7783 1330 : FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
7784 1330 : if (!broken_loop)
7785 1314 : remove_edge (BRANCH_EDGE (entry_bb));
7786 : else
7787 : {
7788 16 : remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
7789 16 : region->outer->cont = NULL;
7790 : }
7791 :
7792 : /* Connect all the blocks. */
7793 1330 : if (!broken_loop)
7794 : {
7795 1314 : ep = find_edge (cont_bb, body_bb);
7796 1314 : if (gimple_omp_for_combined_p (fd->for_stmt))
7797 : {
7798 617 : remove_edge (ep);
7799 617 : ep = NULL;
7800 : }
7801 697 : else if (fd->collapse > 1)
7802 : {
7803 81 : remove_edge (ep);
7804 81 : ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7805 : }
7806 : else
7807 616 : ep->flags = EDGE_TRUE_VALUE;
7808 1931 : find_edge (cont_bb, fin_bb)->flags
7809 1395 : = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7810 : }
7811 :
7812 1330 : set_immediate_dominator (CDI_DOMINATORS, body_bb,
7813 : recompute_dominator (CDI_DOMINATORS, body_bb));
7814 1330 : if (!broken_loop)
7815 1314 : set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7816 : recompute_dominator (CDI_DOMINATORS, fin_bb));
7817 :
7818 1314 : if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
7819 : {
7820 697 : class loop *loop = alloc_loop ();
7821 697 : loop->header = body_bb;
7822 697 : if (collapse_bb == NULL)
7823 616 : loop->latch = cont_bb;
7824 697 : add_loop (loop, body_bb->loop_father);
7825 : }
7826 1330 : }
7827 :
7828 : /* A subroutine of expand_omp_for. Generate code for an OpenACC
7829 : partitioned loop. The lowering here is abstracted, in that the
7830 : loop parameters are passed through internal functions, which are
7831 : further lowered by oacc_device_lower, once we get to the target
7832 : compiler. The loop is of the form:
7833 :
7834 : for (V = B; V LTGT E; V += S) {BODY}
7835 :
7836 : where LTGT is < or >. We may have a specified chunking size, CHUNKING
7837 : (constant 0 for no chunking) and we will have a GWV partitioning
7838 : mask, specifying dimensions over which the loop is to be
7839 : partitioned (see note below). We generate code that looks like
7840 : (this ignores tiling):
7841 :
7842 : <entry_bb> [incoming FALL->body, BRANCH->exit]
7843 : typedef signedintify (typeof (V)) T; // underlying signed integral type
7844 : T range = E - B;
7845 : T chunk_no = 0;
7846 : T DIR = LTGT == '<' ? +1 : -1;
7847 : T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
7848 : T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
7849 :
7850 : <head_bb> [created by splitting end of entry_bb]
7851 : T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
7852 : T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
7853 : if (!(offset LTGT bound)) goto bottom_bb;
7854 :
7855 : <body_bb> [incoming]
7856 : V = B + offset;
7857 : {BODY}
7858 :
7859 : <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
7860 : offset += step;
7861 : if (offset LTGT bound) goto body_bb; [*]
7862 :
7863 : <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
7864 : chunk_no++;
7865 : if (chunk < chunk_max) goto head_bb;
7866 :
7867 : <exit_bb> [incoming]
7868 : V = B + ((range -/+ 1) / S +/- 1) * S [*]
7869 :
7870 : [*] Needed if V live at end of loop. */
7871 :
7872 : static void
7873 11711 : expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
7874 : {
7875 11711 : bool is_oacc_kernels_parallelized
7876 11711 : = (lookup_attribute ("oacc kernels parallelized",
7877 11711 : DECL_ATTRIBUTES (current_function_decl)) != NULL);
7878 11711 : {
7879 11711 : bool is_oacc_kernels
7880 11711 : = (lookup_attribute ("oacc kernels",
7881 11711 : DECL_ATTRIBUTES (current_function_decl)) != NULL);
7882 11711 : if (is_oacc_kernels_parallelized)
7883 386 : gcc_checking_assert (is_oacc_kernels);
7884 : }
7885 23422 : gcc_assert (gimple_in_ssa_p (cfun) == is_oacc_kernels_parallelized);
7886 : /* In the following, some of the 'gimple_in_ssa_p (cfun)' conditionals are
7887 : for SSA specifics, and some are for 'parloops' OpenACC
7888 : 'kernels'-parallelized specifics. */
7889 :
7890 11711 : tree v = fd->loop.v;
7891 11711 : enum tree_code cond_code = fd->loop.cond_code;
7892 11711 : enum tree_code plus_code = PLUS_EXPR;
7893 :
7894 11711 : tree chunk_size = integer_minus_one_node;
7895 11711 : tree gwv = integer_zero_node;
7896 11711 : tree iter_type = TREE_TYPE (v);
7897 11711 : tree diff_type = iter_type;
7898 11711 : tree plus_type = iter_type;
7899 11711 : struct oacc_collapse *counts = NULL;
7900 :
7901 11711 : gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
7902 : == GF_OMP_FOR_KIND_OACC_LOOP);
7903 11711 : gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
7904 11711 : gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
7905 :
7906 11711 : if (POINTER_TYPE_P (iter_type))
7907 : {
7908 52 : plus_code = POINTER_PLUS_EXPR;
7909 52 : plus_type = sizetype;
7910 : }
7911 24124 : for (int ix = fd->collapse; ix--;)
7912 : {
7913 12413 : tree diff_type2 = TREE_TYPE (fd->loops[ix].step);
7914 12413 : if (TYPE_PRECISION (diff_type) < TYPE_PRECISION (diff_type2))
7915 0 : diff_type = diff_type2;
7916 : }
7917 11711 : if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7918 1002 : diff_type = signed_type_for (diff_type);
7919 11711 : if (TYPE_PRECISION (diff_type) < TYPE_PRECISION (integer_type_node))
7920 23 : diff_type = integer_type_node;
7921 :
7922 11711 : basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
7923 11711 : basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
7924 11711 : basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
7925 11711 : basic_block bottom_bb = NULL;
7926 :
7927 : /* entry_bb has two successors; the branch edge is to the exit
7928 : block (or to finalization blocks preceding it), fallthrough edge
7929 : to body. */
7930 11711 : gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7931 :
7932 : /* If cont_bb non-NULL, it has 2 successors. The branch successor is
7933 : body_bb, or to a block whose only successor is the body_bb. Its
7934 : fallthrough successor is the final block (same as the branch
7935 : successor of the entry_bb), possibly via finalization blocks. */
7936 11711 : if (cont_bb)
7937 : {
7938 11672 : basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
7939 11672 : basic_block bed = BRANCH_EDGE (cont_bb)->dest;
7940 :
7941 11672 : gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7942 11672 : gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
7943 : }
7944 : else
7945 39 : gcc_assert (!gimple_in_ssa_p (cfun));
7946 :
7947 11711 : tree chunk_no;
7948 11711 : tree chunk_max = NULL_TREE;
7949 11711 : tree bound, offset;
7950 11711 : tree step = create_tmp_var (diff_type, ".step");
7951 11711 : bool up = cond_code == LT_EXPR;
7952 11871 : tree dir = build_int_cst (diff_type, up ? +1 : -1);
7953 11711 : bool chunking = !gimple_in_ssa_p (cfun);
7954 11711 : bool negating;
7955 :
7956 : /* Tiling vars. */
7957 11711 : tree tile_size = NULL_TREE;
7958 11711 : tree element_s = NULL_TREE;
7959 11711 : tree e_bound = NULL_TREE, e_offset = NULL_TREE, e_step = NULL_TREE;
7960 11711 : basic_block elem_body_bb = NULL;
7961 11711 : basic_block elem_cont_bb = NULL;
7962 :
7963 : /* SSA instances. */
7964 11711 : tree offset_incr = NULL_TREE;
7965 11711 : tree offset_init = NULL_TREE;
7966 :
7967 11711 : gimple_stmt_iterator gsi;
7968 11711 : gassign *ass;
7969 11711 : gcall *call;
7970 11711 : gimple *stmt;
7971 11711 : tree expr;
7972 11711 : location_t loc;
7973 11711 : edge split, be, fte;
7974 :
7975 : /* Split the end of entry_bb to create head_bb. */
7976 11711 : split = split_block (entry_bb, last_nondebug_stmt (entry_bb));
7977 11711 : basic_block head_bb = split->dest;
7978 11711 : entry_bb = split->src;
7979 :
7980 : /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
7981 11711 : gsi = gsi_last_nondebug_bb (entry_bb);
7982 11711 : gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
7983 11711 : loc = gimple_location (for_stmt);
7984 :
7985 11711 : if (gimple_in_ssa_p (cfun))
7986 : {
7987 386 : offset_init = gimple_omp_for_index (for_stmt, 0);
7988 386 : gcc_assert (integer_zerop (fd->loop.n1));
7989 : /* The SSA parallelizer does gang parallelism. */
7990 386 : gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
7991 : }
7992 :
7993 11711 : if (fd->collapse > 1 || fd->tiling)
7994 : {
7995 1188 : gcc_assert (!gimple_in_ssa_p (cfun) && up);
7996 594 : counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
7997 594 : tree total = expand_oacc_collapse_init (fd, &gsi, counts, diff_type,
7998 594 : TREE_TYPE (fd->loop.n2), loc);
7999 :
8000 594 : if (SSA_VAR_P (fd->loop.n2))
8001 : {
8002 107 : total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
8003 : true, GSI_SAME_STMT);
8004 107 : ass = gimple_build_assign (fd->loop.n2, total);
8005 107 : gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
8006 : }
8007 : }
8008 :
8009 11711 : tree b = fd->loop.n1;
8010 11711 : tree e = fd->loop.n2;
8011 11711 : tree s = fd->loop.step;
8012 :
8013 11711 : b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
8014 11711 : e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
8015 :
8016 : /* Convert the step, avoiding possible unsigned->signed overflow. */
8017 11711 : negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
8018 32 : if (negating)
8019 32 : s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
8020 11711 : s = fold_convert (diff_type, s);
8021 11711 : if (negating)
8022 32 : s = fold_build1 (NEGATE_EXPR, diff_type, s);
8023 11711 : s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
8024 :
8025 11711 : if (!chunking)
8026 386 : chunk_size = integer_zero_node;
8027 11711 : expr = fold_convert (diff_type, chunk_size);
8028 11711 : chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
8029 : NULL_TREE, true, GSI_SAME_STMT);
8030 :
8031 11711 : if (fd->tiling)
8032 : {
8033 : /* Determine the tile size and element step,
8034 : modify the outer loop step size. */
8035 177 : tile_size = create_tmp_var (diff_type, ".tile_size");
8036 177 : expr = build_int_cst (diff_type, 1);
8037 461 : for (int ix = 0; ix < fd->collapse; ix++)
8038 284 : expr = fold_build2 (MULT_EXPR, diff_type, counts[ix].tile, expr);
8039 177 : expr = force_gimple_operand_gsi (&gsi, expr, true,
8040 : NULL_TREE, true, GSI_SAME_STMT);
8041 177 : ass = gimple_build_assign (tile_size, expr);
8042 177 : gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
8043 :
8044 177 : element_s = create_tmp_var (diff_type, ".element_s");
8045 177 : ass = gimple_build_assign (element_s, s);
8046 177 : gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
8047 :
8048 177 : expr = fold_build2 (MULT_EXPR, diff_type, s, tile_size);
8049 177 : s = force_gimple_operand_gsi (&gsi, expr, true,
8050 : NULL_TREE, true, GSI_SAME_STMT);
8051 : }
8052 :
8053 : /* Determine the range, avoiding possible unsigned->signed overflow. */
8054 11711 : negating = !up && TYPE_UNSIGNED (iter_type);
8055 23374 : expr = fold_build2 (MINUS_EXPR, plus_type,
8056 : fold_convert (plus_type, negating ? b : e),
8057 : fold_convert (plus_type, negating ? e : b));
8058 11711 : expr = fold_convert (diff_type, expr);
8059 11711 : if (negating)
8060 48 : expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
8061 11711 : tree range = force_gimple_operand_gsi (&gsi, expr, true,
8062 : NULL_TREE, true, GSI_SAME_STMT);
8063 :
8064 11711 : chunk_no = build_int_cst (diff_type, 0);
8065 11711 : if (chunking)
8066 : {
8067 11325 : gcc_assert (!gimple_in_ssa_p (cfun));
8068 :
8069 11325 : expr = chunk_no;
8070 11325 : chunk_max = create_tmp_var (diff_type, ".chunk_max");
8071 11325 : chunk_no = create_tmp_var (diff_type, ".chunk_no");
8072 :
8073 11325 : ass = gimple_build_assign (chunk_no, expr);
8074 11325 : gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
8075 :
8076 11325 : call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
8077 : build_int_cst (integer_type_node,
8078 : IFN_GOACC_LOOP_CHUNKS),
8079 : dir, range, s, chunk_size, gwv);
8080 11325 : gimple_call_set_lhs (call, chunk_max);
8081 11325 : gimple_set_location (call, loc);
8082 11325 : gsi_insert_before (&gsi, call, GSI_SAME_STMT);
8083 : }
8084 : else
8085 : chunk_size = chunk_no;
8086 :
8087 11711 : call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
8088 : build_int_cst (integer_type_node,
8089 : IFN_GOACC_LOOP_STEP),
8090 : dir, range, s, chunk_size, gwv);
8091 11711 : gimple_call_set_lhs (call, step);
8092 11711 : gimple_set_location (call, loc);
8093 11711 : gsi_insert_before (&gsi, call, GSI_SAME_STMT);
8094 :
8095 : /* Remove the GIMPLE_OMP_FOR. */
8096 11711 : gsi_remove (&gsi, true);
8097 :
8098 : /* Fixup edges from head_bb. */
8099 11711 : be = BRANCH_EDGE (head_bb);
8100 11711 : fte = FALLTHRU_EDGE (head_bb);
8101 11711 : be->flags |= EDGE_FALSE_VALUE;
8102 11711 : fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
8103 :
8104 11711 : basic_block body_bb = fte->dest;
8105 :
8106 11711 : if (gimple_in_ssa_p (cfun))
8107 : {
8108 386 : gsi = gsi_last_nondebug_bb (cont_bb);
8109 386 : gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8110 :
8111 386 : offset = gimple_omp_continue_control_use (cont_stmt);
8112 386 : offset_incr = gimple_omp_continue_control_def (cont_stmt);
8113 : }
8114 : else
8115 : {
8116 11325 : offset = create_tmp_var (diff_type, ".offset");
8117 11325 : offset_init = offset_incr = offset;
8118 : }
8119 11711 : bound = create_tmp_var (TREE_TYPE (offset), ".bound");
8120 :
8121 : /* Loop offset & bound go into head_bb. */
8122 11711 : gsi = gsi_start_bb (head_bb);
8123 :
8124 11711 : call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
8125 : build_int_cst (integer_type_node,
8126 : IFN_GOACC_LOOP_OFFSET),
8127 : dir, range, s,
8128 : chunk_size, gwv, chunk_no);
8129 11711 : gimple_call_set_lhs (call, offset_init);
8130 11711 : gimple_set_location (call, loc);
8131 11711 : gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
8132 :
8133 11711 : call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
8134 : build_int_cst (integer_type_node,
8135 : IFN_GOACC_LOOP_BOUND),
8136 : dir, range, s,
8137 : chunk_size, gwv, offset_init);
8138 11711 : gimple_call_set_lhs (call, bound);
8139 11711 : gimple_set_location (call, loc);
8140 11711 : gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
8141 :
8142 11711 : expr = build2 (cond_code, boolean_type_node, offset_init, bound);
8143 11711 : gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
8144 : GSI_CONTINUE_LINKING);
8145 :
8146 : /* V assignment goes into body_bb. */
8147 11711 : if (!gimple_in_ssa_p (cfun))
8148 : {
8149 11325 : gsi = gsi_start_bb (body_bb);
8150 :
8151 11325 : expr = build2 (plus_code, iter_type, b,
8152 : fold_convert (plus_type, offset));
8153 11325 : expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
8154 : true, GSI_SAME_STMT);
8155 11325 : ass = gimple_build_assign (v, expr);
8156 11325 : gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
8157 :
8158 11325 : if (fd->collapse > 1 || fd->tiling)
8159 594 : expand_oacc_collapse_vars (fd, false, &gsi, counts, v, diff_type);
8160 :
8161 11325 : if (fd->tiling)
8162 : {
8163 : /* Determine the range of the element loop -- usually simply
8164 : the tile_size, but could be smaller if the final
8165 : iteration of the outer loop is a partial tile. */
8166 177 : tree e_range = create_tmp_var (diff_type, ".e_range");
8167 :
8168 177 : expr = build2 (MIN_EXPR, diff_type,
8169 : build2 (MINUS_EXPR, diff_type, bound, offset),
8170 : build2 (MULT_EXPR, diff_type, tile_size,
8171 : element_s));
8172 177 : expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
8173 : true, GSI_SAME_STMT);
8174 177 : ass = gimple_build_assign (e_range, expr);
8175 177 : gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
8176 :
8177 : /* Determine bound, offset & step of inner loop. */
8178 177 : e_bound = create_tmp_var (diff_type, ".e_bound");
8179 177 : e_offset = create_tmp_var (diff_type, ".e_offset");
8180 177 : e_step = create_tmp_var (diff_type, ".e_step");
8181 :
8182 : /* Mark these as element loops. */
8183 177 : tree t, e_gwv = integer_minus_one_node;
8184 177 : tree chunk = build_int_cst (diff_type, 0); /* Never chunked. */
8185 :
8186 177 : t = build_int_cst (integer_type_node, IFN_GOACC_LOOP_OFFSET);
8187 177 : call = gimple_build_call_internal (IFN_GOACC_LOOP, 7, t, dir, e_range,
8188 : element_s, chunk, e_gwv, chunk);
8189 177 : gimple_call_set_lhs (call, e_offset);
8190 177 : gimple_set_location (call, loc);
8191 177 : gsi_insert_before (&gsi, call, GSI_SAME_STMT);
8192 :
8193 177 : t = build_int_cst (integer_type_node, IFN_GOACC_LOOP_BOUND);
8194 177 : call = gimple_build_call_internal (IFN_GOACC_LOOP, 7, t, dir, e_range,
8195 : element_s, chunk, e_gwv, e_offset);
8196 177 : gimple_call_set_lhs (call, e_bound);
8197 177 : gimple_set_location (call, loc);
8198 177 : gsi_insert_before (&gsi, call, GSI_SAME_STMT);
8199 :
8200 177 : t = build_int_cst (integer_type_node, IFN_GOACC_LOOP_STEP);
8201 177 : call = gimple_build_call_internal (IFN_GOACC_LOOP, 6, t, dir, e_range,
8202 : element_s, chunk, e_gwv);
8203 177 : gimple_call_set_lhs (call, e_step);
8204 177 : gimple_set_location (call, loc);
8205 177 : gsi_insert_before (&gsi, call, GSI_SAME_STMT);
8206 :
8207 : /* Add test and split block. */
8208 177 : expr = build2 (cond_code, boolean_type_node, e_offset, e_bound);
8209 177 : stmt = gimple_build_cond_empty (expr);
8210 177 : gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
8211 177 : split = split_block (body_bb, stmt);
8212 177 : elem_body_bb = split->dest;
8213 177 : if (cont_bb == body_bb)
8214 146 : cont_bb = elem_body_bb;
8215 177 : body_bb = split->src;
8216 :
8217 177 : split->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
8218 :
8219 : /* Add a dummy exit for the tiled block when cont_bb is missing. */
8220 177 : if (cont_bb == NULL)
8221 : {
8222 5 : edge e = make_edge (body_bb, exit_bb, EDGE_FALSE_VALUE);
8223 5 : e->probability = profile_probability::even ();
8224 5 : split->probability = profile_probability::even ();
8225 : }
8226 :
8227 : /* Initialize the user's loop vars. */
8228 177 : gsi = gsi_start_bb (elem_body_bb);
8229 177 : expand_oacc_collapse_vars (fd, true, &gsi, counts, e_offset,
8230 : diff_type);
8231 : }
8232 : }
8233 :
8234 : /* Loop increment goes into cont_bb. If this is not a loop, we
8235 : will have spawned threads as if it was, and each one will
8236 : execute one iteration. The specification is not explicit about
8237 : whether such constructs are ill-formed or not, and they can
8238 : occur, especially when noreturn routines are involved. */
8239 11711 : if (cont_bb)
8240 : {
8241 11672 : gsi = gsi_last_nondebug_bb (cont_bb);
8242 11672 : gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8243 11672 : loc = gimple_location (cont_stmt);
8244 :
8245 11672 : if (fd->tiling)
8246 : {
8247 : /* Insert element loop increment and test. */
8248 172 : expr = build2 (PLUS_EXPR, diff_type, e_offset, e_step);
8249 172 : expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
8250 : true, GSI_SAME_STMT);
8251 172 : ass = gimple_build_assign (e_offset, expr);
8252 172 : gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
8253 172 : expr = build2 (cond_code, boolean_type_node, e_offset, e_bound);
8254 :
8255 172 : stmt = gimple_build_cond_empty (expr);
8256 172 : gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
8257 172 : split = split_block (cont_bb, stmt);
8258 172 : elem_cont_bb = split->src;
8259 172 : cont_bb = split->dest;
8260 :
8261 172 : split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
8262 172 : split->probability = profile_probability::unlikely ().guessed ();
8263 172 : edge latch_edge
8264 172 : = make_edge (elem_cont_bb, elem_body_bb, EDGE_TRUE_VALUE);
8265 172 : latch_edge->probability = profile_probability::likely ().guessed ();
8266 :
8267 172 : edge skip_edge = make_edge (body_bb, cont_bb, EDGE_FALSE_VALUE);
8268 172 : skip_edge->probability = profile_probability::unlikely ().guessed ();
8269 172 : edge loop_entry_edge = EDGE_SUCC (body_bb, 1 - skip_edge->dest_idx);
8270 172 : loop_entry_edge->probability
8271 172 : = profile_probability::likely ().guessed ();
8272 :
8273 172 : gsi = gsi_for_stmt (cont_stmt);
8274 : }
8275 :
8276 : /* Increment offset. */
8277 11672 : if (gimple_in_ssa_p (cfun))
8278 386 : expr = build2 (plus_code, iter_type, offset,
8279 : fold_convert (plus_type, step));
8280 : else
8281 11286 : expr = build2 (PLUS_EXPR, diff_type, offset, step);
8282 11672 : expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
8283 : true, GSI_SAME_STMT);
8284 11672 : ass = gimple_build_assign (offset_incr, expr);
8285 11672 : gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
8286 11672 : expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
8287 11672 : gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
8288 :
8289 : /* Remove the GIMPLE_OMP_CONTINUE. */
8290 11672 : gsi_remove (&gsi, true);
8291 :
8292 : /* Fixup edges from cont_bb. */
8293 11672 : be = BRANCH_EDGE (cont_bb);
8294 11672 : fte = FALLTHRU_EDGE (cont_bb);
8295 11672 : be->flags |= EDGE_TRUE_VALUE;
8296 11672 : fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
8297 :
8298 11672 : if (chunking)
8299 : {
8300 : /* Split the beginning of exit_bb to make bottom_bb. We
8301 : need to insert a nop at the start, because splitting is
8302 : after a stmt, not before. */
8303 11286 : gsi = gsi_start_bb (exit_bb);
8304 11286 : stmt = gimple_build_nop ();
8305 11286 : gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
8306 11286 : split = split_block (exit_bb, stmt);
8307 11286 : bottom_bb = split->src;
8308 11286 : exit_bb = split->dest;
8309 11286 : gsi = gsi_last_bb (bottom_bb);
8310 :
8311 : /* Chunk increment and test goes into bottom_bb. */
8312 11286 : expr = build2 (PLUS_EXPR, diff_type, chunk_no,
8313 : build_int_cst (diff_type, 1));
8314 11286 : ass = gimple_build_assign (chunk_no, expr);
8315 11286 : gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
8316 :
8317 : /* Chunk test at end of bottom_bb. */
8318 11286 : expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
8319 11286 : gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
8320 : GSI_CONTINUE_LINKING);
8321 :
8322 : /* Fixup edges from bottom_bb. */
8323 11286 : split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
8324 11286 : split->probability = profile_probability::unlikely ().guessed ();
8325 11286 : edge latch_edge = make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
8326 11286 : latch_edge->probability = profile_probability::likely ().guessed ();
8327 : }
8328 : }
8329 :
8330 11711 : gsi = gsi_last_nondebug_bb (exit_bb);
8331 11711 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8332 11711 : loc = gimple_location (gsi_stmt (gsi));
8333 :
8334 11711 : if (!gimple_in_ssa_p (cfun))
8335 : {
8336 : /* Insert the final value of V, in case it is live. This is the
8337 : value for the only thread that survives past the join. */
8338 11325 : expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
8339 11325 : expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
8340 11325 : expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
8341 11325 : expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
8342 11325 : expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
8343 11325 : expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
8344 : true, GSI_SAME_STMT);
8345 11325 : ass = gimple_build_assign (v, expr);
8346 11325 : gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
8347 : }
8348 :
8349 : /* Remove the OMP_RETURN. */
8350 11711 : gsi_remove (&gsi, true);
8351 :
8352 11711 : if (cont_bb)
8353 : {
8354 : /* We now have one, two or three nested loops. Update the loop
8355 : structures. */
8356 11672 : class loop *parent = entry_bb->loop_father;
8357 11672 : class loop *body = body_bb->loop_father;
8358 :
8359 11672 : if (chunking)
8360 : {
8361 11286 : class loop *chunk_loop = alloc_loop ();
8362 11286 : chunk_loop->header = head_bb;
8363 11286 : chunk_loop->latch = bottom_bb;
8364 11286 : add_loop (chunk_loop, parent);
8365 11286 : parent = chunk_loop;
8366 : }
8367 386 : else if (parent != body)
8368 : {
8369 386 : gcc_assert (body->header == body_bb);
8370 386 : gcc_assert (body->latch == cont_bb
8371 : || single_pred (body->latch) == cont_bb);
8372 : parent = NULL;
8373 : }
8374 :
8375 11286 : if (parent)
8376 : {
8377 11286 : class loop *body_loop = alloc_loop ();
8378 11286 : body_loop->header = body_bb;
8379 11286 : body_loop->latch = cont_bb;
8380 11286 : add_loop (body_loop, parent);
8381 :
8382 11286 : if (fd->tiling)
8383 : {
8384 : /* Insert tiling's element loop. */
8385 172 : class loop *inner_loop = alloc_loop ();
8386 172 : inner_loop->header = elem_body_bb;
8387 172 : inner_loop->latch = elem_cont_bb;
8388 172 : add_loop (inner_loop, body_loop);
8389 : }
8390 : }
8391 : }
8392 11711 : }
8393 :
8394 : /* Expand the OMP loop defined by REGION. */
8395 :
8396 : static void
8397 47801 : expand_omp_for (struct omp_region *region, gimple *inner_stmt)
8398 : {
8399 47801 : struct omp_for_data fd;
8400 47801 : struct omp_for_data_loop *loops;
8401 :
8402 47801 : loops = XALLOCAVEC (struct omp_for_data_loop,
8403 : gimple_omp_for_collapse
8404 : (last_nondebug_stmt (region->entry)));
8405 47801 : omp_extract_for_data (as_a <gomp_for *> (last_nondebug_stmt (region->entry)),
8406 : &fd, loops);
8407 47801 : region->sched_kind = fd.sched_kind;
8408 47801 : region->sched_modifiers = fd.sched_modifiers;
8409 47801 : region->has_lastprivate_conditional = fd.lastprivate_conditional != 0;
8410 47801 : if (fd.non_rect && !gimple_omp_for_combined_into_p (fd.for_stmt))
8411 : {
8412 2344 : for (int i = fd.first_nonrect; i <= fd.last_nonrect; i++)
8413 1644 : if ((loops[i].m1 || loops[i].m2)
8414 731 : && (loops[i].m1 == NULL_TREE
8415 506 : || TREE_CODE (loops[i].m1) == INTEGER_CST)
8416 612 : && (loops[i].m2 == NULL_TREE
8417 343 : || TREE_CODE (loops[i].m2) == INTEGER_CST)
8418 596 : && TREE_CODE (loops[i].step) == INTEGER_CST
8419 586 : && TREE_CODE (loops[i - loops[i].outer].step) == INTEGER_CST)
8420 : {
8421 586 : tree t;
8422 586 : tree itype = TREE_TYPE (loops[i].v);
8423 586 : if (loops[i].m1 && loops[i].m2)
8424 108 : t = fold_build2 (MINUS_EXPR, itype, loops[i].m2, loops[i].m1);
8425 478 : else if (loops[i].m1)
8426 267 : t = fold_build1 (NEGATE_EXPR, itype, loops[i].m1);
8427 : else
8428 : t = loops[i].m2;
8429 586 : t = fold_build2 (MULT_EXPR, itype, t,
8430 : fold_convert (itype,
8431 : loops[i - loops[i].outer].step));
8432 586 : if (TYPE_UNSIGNED (itype) && loops[i].cond_code == GT_EXPR)
8433 3 : t = fold_build2 (TRUNC_MOD_EXPR, itype,
8434 : fold_build1 (NEGATE_EXPR, itype, t),
8435 : fold_build1 (NEGATE_EXPR, itype,
8436 : fold_convert (itype,
8437 : loops[i].step)));
8438 : else
8439 583 : t = fold_build2 (TRUNC_MOD_EXPR, itype, t,
8440 : fold_convert (itype, loops[i].step));
8441 586 : if (integer_nonzerop (t))
8442 8 : error_at (gimple_location (fd.for_stmt),
8443 : "invalid OpenMP non-rectangular loop step; "
8444 : "%<(%E - %E) * %E%> is not a multiple of loop %d "
8445 : "step %qE",
8446 8 : loops[i].m2 ? loops[i].m2 : integer_zero_node,
8447 8 : loops[i].m1 ? loops[i].m1 : integer_zero_node,
8448 8 : loops[i - loops[i].outer].step, i + 1,
8449 : loops[i].step);
8450 : }
8451 : }
8452 :
8453 47801 : gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
8454 47801 : BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
8455 47801 : FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
8456 47801 : if (region->cont)
8457 : {
8458 45514 : gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
8459 45514 : BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
8460 45514 : FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
8461 : }
8462 : else
8463 : /* If there isn't a continue then this is a degenerate case where
8464 : the introduction of abnormal edges during lowering will prevent
8465 : original loops from being detected. Fix that up. */
8466 2287 : loops_state_set (LOOPS_NEED_FIXUP);
8467 :
8468 47801 : if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD)
8469 9374 : expand_omp_simd (region, &fd);
8470 38427 : else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
8471 : {
8472 11711 : gcc_assert (!inner_stmt && !fd.non_rect);
8473 11711 : expand_oacc_for (region, &fd);
8474 : }
8475 26716 : else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
8476 : {
8477 2660 : if (gimple_omp_for_combined_into_p (fd.for_stmt))
8478 1330 : expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
8479 : else
8480 1330 : expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
8481 : }
8482 24056 : else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
8483 20374 : && !fd.have_ordered)
8484 : {
8485 19922 : if (fd.chunk_size == NULL)
8486 14067 : expand_omp_for_static_nochunk (region, &fd, inner_stmt);
8487 : else
8488 5855 : expand_omp_for_static_chunk (region, &fd, inner_stmt);
8489 : }
8490 : else
8491 : {
8492 4134 : int fn_index, start_ix, next_ix;
8493 4134 : unsigned HOST_WIDE_INT sched = 0;
8494 4134 : tree sched_arg = NULL_TREE;
8495 :
8496 4134 : gcc_assert (gimple_omp_for_kind (fd.for_stmt)
8497 : == GF_OMP_FOR_KIND_FOR && !fd.non_rect);
8498 4134 : if (fd.chunk_size == NULL
8499 1665 : && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
8500 0 : fd.chunk_size = integer_zero_node;
8501 4134 : switch (fd.sched_kind)
8502 : {
8503 1665 : case OMP_CLAUSE_SCHEDULE_RUNTIME:
8504 1665 : if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC) != 0
8505 28 : && fd.lastprivate_conditional == 0)
8506 : {
8507 28 : gcc_assert (!fd.have_ordered);
8508 : fn_index = 6;
8509 : sched = 4;
8510 : }
8511 1637 : else if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_MONOTONIC) == 0
8512 1605 : && !fd.have_ordered
8513 1561 : && fd.lastprivate_conditional == 0)
8514 : fn_index = 7;
8515 : else
8516 : {
8517 87 : fn_index = 3;
8518 87 : sched = (HOST_WIDE_INT_1U << 31);
8519 : }
8520 : break;
8521 2017 : case OMP_CLAUSE_SCHEDULE_DYNAMIC:
8522 2017 : case OMP_CLAUSE_SCHEDULE_GUIDED:
8523 2017 : if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_MONOTONIC) == 0
8524 1961 : && !fd.have_ordered
8525 1798 : && fd.lastprivate_conditional == 0)
8526 : {
8527 1771 : fn_index = 3 + fd.sched_kind;
8528 1771 : sched = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_GUIDED) + 2;
8529 : break;
8530 : }
8531 246 : fn_index = fd.sched_kind;
8532 246 : sched = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_GUIDED) + 2;
8533 246 : sched += (HOST_WIDE_INT_1U << 31);
8534 246 : break;
8535 452 : case OMP_CLAUSE_SCHEDULE_STATIC:
8536 452 : gcc_assert (fd.have_ordered);
8537 : fn_index = 0;
8538 : sched = (HOST_WIDE_INT_1U << 31) + 1;
8539 : break;
8540 0 : default:
8541 0 : gcc_unreachable ();
8542 : }
8543 4134 : if (!fd.ordered)
8544 3799 : fn_index += fd.have_ordered * 8;
8545 4134 : if (fd.ordered)
8546 335 : start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
8547 : else
8548 3799 : start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
8549 4134 : next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
8550 4134 : if (fd.have_reductemp || fd.have_pointer_condtemp)
8551 : {
8552 169 : if (fd.ordered)
8553 : start_ix = (int)BUILT_IN_GOMP_LOOP_DOACROSS_START;
8554 133 : else if (fd.have_ordered)
8555 : start_ix = (int)BUILT_IN_GOMP_LOOP_ORDERED_START;
8556 : else
8557 95 : start_ix = (int)BUILT_IN_GOMP_LOOP_START;
8558 169 : sched_arg = build_int_cstu (long_integer_type_node, sched);
8559 169 : if (!fd.chunk_size)
8560 38 : fd.chunk_size = integer_zero_node;
8561 : }
8562 4134 : if (fd.iter_type == long_long_unsigned_type_node)
8563 : {
8564 778 : start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
8565 : - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
8566 778 : next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
8567 : - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
8568 : }
8569 4134 : expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
8570 : (enum built_in_function) next_ix, sched_arg,
8571 : inner_stmt);
8572 : }
8573 47801 : }
8574 :
8575 : /* Expand code for an OpenMP sections directive. In pseudo code, we generate
8576 :
8577 : v = GOMP_sections_start (n);
8578 : L0:
8579 : switch (v)
8580 : {
8581 : case 0:
8582 : goto L2;
8583 : case 1:
8584 : section 1;
8585 : goto L1;
8586 : case 2:
8587 : ...
8588 : case n:
8589 : ...
8590 : default:
8591 : abort ();
8592 : }
8593 : L1:
8594 : v = GOMP_sections_next ();
8595 : goto L0;
8596 : L2:
8597 : reduction;
8598 :
8599 : If this is a combined parallel sections, replace the call to
8600 : GOMP_sections_start with call to GOMP_sections_next. */
8601 :
8602 : static void
8603 386 : expand_omp_sections (struct omp_region *region)
8604 : {
8605 386 : tree t, u, vin = NULL, vmain, vnext, l2;
8606 386 : unsigned len;
8607 386 : basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
8608 386 : gimple_stmt_iterator si, switch_si;
8609 386 : gomp_sections *sections_stmt;
8610 386 : gimple *stmt;
8611 386 : gomp_continue *cont;
8612 386 : edge_iterator ei;
8613 386 : edge e;
8614 386 : struct omp_region *inner;
8615 386 : unsigned i, casei;
8616 386 : bool exit_reachable = region->cont != NULL;
8617 :
8618 386 : gcc_assert (region->exit != NULL);
8619 386 : entry_bb = region->entry;
8620 386 : l0_bb = single_succ (entry_bb);
8621 386 : l1_bb = region->cont;
8622 386 : l2_bb = region->exit;
8623 735 : if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
8624 322 : l2 = gimple_block_label (l2_bb);
8625 : else
8626 : {
8627 : /* This can happen if there are reductions. */
8628 64 : len = EDGE_COUNT (l0_bb->succs);
8629 64 : gcc_assert (len > 0);
8630 64 : e = EDGE_SUCC (l0_bb, len - 1);
8631 64 : si = gsi_last_nondebug_bb (e->dest);
8632 64 : l2 = NULL_TREE;
8633 64 : if (gsi_end_p (si)
8634 64 : || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8635 64 : l2 = gimple_block_label (e->dest);
8636 : else
8637 0 : FOR_EACH_EDGE (e, ei, l0_bb->succs)
8638 : {
8639 0 : si = gsi_last_nondebug_bb (e->dest);
8640 0 : if (gsi_end_p (si)
8641 0 : || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8642 : {
8643 0 : l2 = gimple_block_label (e->dest);
8644 0 : break;
8645 : }
8646 : }
8647 : }
8648 386 : if (exit_reachable)
8649 340 : default_bb = create_empty_bb (l1_bb->prev_bb);
8650 : else
8651 46 : default_bb = create_empty_bb (l0_bb);
8652 :
8653 : /* We will build a switch() with enough cases for all the
8654 : GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
8655 : and a default case to abort if something goes wrong. */
8656 386 : len = EDGE_COUNT (l0_bb->succs);
8657 :
8658 : /* Use vec::quick_push on label_vec throughout, since we know the size
8659 : in advance. */
8660 386 : auto_vec<tree> label_vec (len);
8661 :
8662 : /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8663 : GIMPLE_OMP_SECTIONS statement. */
8664 386 : si = gsi_last_nondebug_bb (entry_bb);
8665 386 : sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
8666 386 : gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8667 386 : vin = gimple_omp_sections_control (sections_stmt);
8668 386 : tree clauses = gimple_omp_sections_clauses (sections_stmt);
8669 386 : tree reductmp = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
8670 386 : tree condtmp = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
8671 386 : tree cond_var = NULL_TREE;
8672 386 : if (reductmp || condtmp)
8673 : {
8674 18 : tree reductions = null_pointer_node, mem = null_pointer_node;
8675 18 : tree memv = NULL_TREE, condtemp = NULL_TREE;
8676 18 : gimple_stmt_iterator gsi = gsi_none ();
8677 18 : gimple *g = NULL;
8678 18 : if (reductmp)
8679 : {
8680 8 : reductions = OMP_CLAUSE_DECL (reductmp);
8681 8 : gcc_assert (TREE_CODE (reductions) == SSA_NAME);
8682 8 : g = SSA_NAME_DEF_STMT (reductions);
8683 8 : reductions = gimple_assign_rhs1 (g);
8684 8 : OMP_CLAUSE_DECL (reductmp) = reductions;
8685 8 : gsi = gsi_for_stmt (g);
8686 : }
8687 : else
8688 10 : gsi = si;
8689 18 : if (condtmp)
8690 : {
8691 12 : condtemp = OMP_CLAUSE_DECL (condtmp);
8692 12 : tree c = omp_find_clause (OMP_CLAUSE_CHAIN (condtmp),
8693 : OMP_CLAUSE__CONDTEMP_);
8694 12 : cond_var = OMP_CLAUSE_DECL (c);
8695 12 : tree type = TREE_TYPE (condtemp);
8696 12 : memv = create_tmp_var (type);
8697 12 : TREE_ADDRESSABLE (memv) = 1;
8698 12 : unsigned cnt = 0;
8699 74 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
8700 62 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
8701 62 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
8702 24 : ++cnt;
8703 12 : unsigned HOST_WIDE_INT sz
8704 12 : = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type))) * cnt;
8705 12 : expand_omp_build_assign (&gsi, memv, build_int_cst (type, sz),
8706 : false);
8707 12 : mem = build_fold_addr_expr (memv);
8708 : }
8709 18 : t = build_int_cst (unsigned_type_node, len - 1);
8710 18 : u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS2_START);
8711 18 : stmt = gimple_build_call (u, 3, t, reductions, mem);
8712 18 : gimple_call_set_lhs (stmt, vin);
8713 18 : gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
8714 18 : if (condtmp)
8715 : {
8716 12 : expand_omp_build_assign (&gsi, condtemp, memv, false);
8717 12 : tree t = build2 (PLUS_EXPR, TREE_TYPE (cond_var),
8718 12 : vin, build_one_cst (TREE_TYPE (cond_var)));
8719 12 : expand_omp_build_assign (&gsi, cond_var, t, false);
8720 : }
8721 18 : if (reductmp)
8722 : {
8723 8 : gsi_remove (&gsi, true);
8724 8 : release_ssa_name (gimple_assign_lhs (g));
8725 : }
8726 : }
8727 368 : else if (!is_combined_parallel (region))
8728 : {
8729 : /* If we are not inside a combined parallel+sections region,
8730 : call GOMP_sections_start. */
8731 252 : t = build_int_cst (unsigned_type_node, len - 1);
8732 252 : u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8733 252 : stmt = gimple_build_call (u, 1, t);
8734 : }
8735 : else
8736 : {
8737 : /* Otherwise, call GOMP_sections_next. */
8738 116 : u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8739 116 : stmt = gimple_build_call (u, 0);
8740 : }
8741 386 : if (!reductmp && !condtmp)
8742 : {
8743 368 : gimple_call_set_lhs (stmt, vin);
8744 368 : gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8745 : }
8746 386 : gsi_remove (&si, true);
8747 :
8748 : /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8749 : L0_BB. */
8750 386 : switch_si = gsi_last_nondebug_bb (l0_bb);
8751 386 : gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8752 386 : if (exit_reachable)
8753 : {
8754 340 : cont = as_a <gomp_continue *> (last_nondebug_stmt (l1_bb));
8755 340 : gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8756 340 : vmain = gimple_omp_continue_control_use (cont);
8757 340 : vnext = gimple_omp_continue_control_def (cont);
8758 : }
8759 : else
8760 : {
8761 : vmain = vin;
8762 : vnext = NULL_TREE;
8763 : }
8764 :
8765 386 : t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8766 386 : label_vec.quick_push (t);
8767 386 : i = 1;
8768 :
8769 : /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8770 386 : for (inner = region->inner, casei = 1;
8771 1276 : inner;
8772 890 : inner = inner->next, i++, casei++)
8773 : {
8774 890 : basic_block s_entry_bb, s_exit_bb;
8775 :
8776 : /* Skip optional reduction region. */
8777 890 : if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8778 : {
8779 27 : --i;
8780 27 : --casei;
8781 27 : continue;
8782 : }
8783 :
8784 863 : s_entry_bb = inner->entry;
8785 863 : s_exit_bb = inner->exit;
8786 :
8787 863 : t = gimple_block_label (s_entry_bb);
8788 863 : u = build_int_cst (unsigned_type_node, casei);
8789 863 : u = build_case_label (u, NULL, t);
8790 863 : label_vec.quick_push (u);
8791 :
8792 863 : si = gsi_last_nondebug_bb (s_entry_bb);
8793 863 : gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8794 863 : gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8795 863 : gsi_remove (&si, true);
8796 863 : single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8797 :
8798 863 : if (s_exit_bb == NULL)
8799 122 : continue;
8800 :
8801 741 : si = gsi_last_nondebug_bb (s_exit_bb);
8802 741 : gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8803 741 : gsi_remove (&si, true);
8804 :
8805 741 : single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8806 : }
8807 :
8808 : /* Error handling code goes in DEFAULT_BB. */
8809 386 : t = gimple_block_label (default_bb);
8810 386 : u = build_case_label (NULL, NULL, t);
8811 386 : make_edge (l0_bb, default_bb, 0);
8812 386 : add_bb_to_loop (default_bb, current_loops->tree_root);
8813 :
8814 386 : stmt = gimple_build_switch (vmain, u, label_vec);
8815 386 : gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8816 386 : gsi_remove (&switch_si, true);
8817 :
8818 386 : si = gsi_start_bb (default_bb);
8819 386 : stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8820 386 : gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8821 :
8822 386 : if (exit_reachable)
8823 : {
8824 340 : tree bfn_decl;
8825 :
8826 : /* Code to get the next section goes in L1_BB. */
8827 340 : si = gsi_last_nondebug_bb (l1_bb);
8828 340 : gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8829 :
8830 340 : bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8831 340 : stmt = gimple_build_call (bfn_decl, 0);
8832 340 : gimple_call_set_lhs (stmt, vnext);
8833 340 : gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8834 340 : if (cond_var)
8835 : {
8836 12 : tree t = build2 (PLUS_EXPR, TREE_TYPE (cond_var),
8837 12 : vnext, build_one_cst (TREE_TYPE (cond_var)));
8838 12 : expand_omp_build_assign (&si, cond_var, t, false);
8839 : }
8840 340 : gsi_remove (&si, true);
8841 :
8842 340 : single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8843 : }
8844 :
8845 : /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8846 386 : si = gsi_last_nondebug_bb (l2_bb);
8847 386 : if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8848 255 : t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8849 131 : else if (gimple_omp_return_lhs (gsi_stmt (si)))
8850 0 : t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8851 : else
8852 131 : t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8853 386 : stmt = gimple_build_call (t, 0);
8854 386 : if (gimple_omp_return_lhs (gsi_stmt (si)))
8855 0 : gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8856 386 : gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8857 386 : gsi_remove (&si, true);
8858 :
8859 386 : set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8860 386 : }
8861 :
8862 : /* Expand code for an OpenMP single or scope directive. We've already expanded
8863 : much of the code, here we simply place the GOMP_barrier call. */
8864 :
8865 : static void
8866 1288 : expand_omp_single (struct omp_region *region)
8867 : {
8868 1288 : basic_block entry_bb, exit_bb;
8869 1288 : gimple_stmt_iterator si;
8870 :
8871 1288 : entry_bb = region->entry;
8872 1288 : exit_bb = region->exit;
8873 :
8874 1288 : si = gsi_last_nondebug_bb (entry_bb);
8875 1288 : enum gimple_code code = gimple_code (gsi_stmt (si));
8876 1288 : gcc_assert (code == GIMPLE_OMP_SINGLE || code == GIMPLE_OMP_SCOPE);
8877 1288 : gsi_remove (&si, true);
8878 1288 : single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8879 :
8880 1288 : if (exit_bb == NULL)
8881 : {
8882 8 : gcc_assert (code == GIMPLE_OMP_SCOPE);
8883 8 : return;
8884 : }
8885 :
8886 1280 : si = gsi_last_nondebug_bb (exit_bb);
8887 1280 : if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8888 : {
8889 1001 : tree t = gimple_omp_return_lhs (gsi_stmt (si));
8890 1001 : gsi_insert_after (&si,
8891 : omp_build_barrier (t, GOMP_BARRIER_IMPLICIT_WORKSHARE),
8892 : GSI_SAME_STMT);
8893 : }
8894 1280 : gsi_remove (&si, true);
8895 1280 : single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8896 : }
8897 :
8898 : /* Generic expansion for OpenMP synchronization directives: master,
8899 : ordered and critical. All we need to do here is remove the entry
8900 : and exit markers for REGION. */
8901 :
8902 : static void
8903 10872 : expand_omp_synch (struct omp_region *region)
8904 : {
8905 10872 : basic_block entry_bb, exit_bb;
8906 10872 : gimple_stmt_iterator si;
8907 :
8908 10872 : entry_bb = region->entry;
8909 10872 : exit_bb = region->exit;
8910 :
8911 10872 : si = gsi_last_nondebug_bb (entry_bb);
8912 10872 : gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8913 : || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8914 : || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASKED
8915 : || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8916 : || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8917 : || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8918 : || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8919 10872 : if (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS
8920 10872 : && gimple_omp_teams_host (as_a <gomp_teams *> (gsi_stmt (si))))
8921 : {
8922 2572 : expand_omp_taskreg (region);
8923 2572 : return;
8924 : }
8925 8300 : gsi_remove (&si, true);
8926 8300 : single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8927 :
8928 8300 : if (exit_bb)
8929 : {
8930 7742 : si = gsi_last_nondebug_bb (exit_bb);
8931 7742 : gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8932 7742 : gsi_remove (&si, true);
8933 7742 : single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8934 : }
8935 : }
8936 :
8937 : /* Translate enum omp_memory_order to enum memmodel for the embedded
8938 : fail clause in there. */
8939 :
8940 : static enum memmodel
8941 2936 : omp_memory_order_to_fail_memmodel (enum omp_memory_order mo)
8942 : {
8943 2936 : switch (mo & OMP_FAIL_MEMORY_ORDER_MASK)
8944 : {
8945 2665 : case OMP_FAIL_MEMORY_ORDER_UNSPECIFIED:
8946 2665 : switch (mo & OMP_MEMORY_ORDER_MASK)
8947 : {
8948 : case OMP_MEMORY_ORDER_RELAXED: return MEMMODEL_RELAXED;
8949 : case OMP_MEMORY_ORDER_ACQUIRE: return MEMMODEL_ACQUIRE;
8950 : case OMP_MEMORY_ORDER_RELEASE: return MEMMODEL_RELAXED;
8951 : case OMP_MEMORY_ORDER_ACQ_REL: return MEMMODEL_ACQUIRE;
8952 : case OMP_MEMORY_ORDER_SEQ_CST: return MEMMODEL_SEQ_CST;
8953 0 : default: break;
8954 : }
8955 0 : gcc_unreachable ();
8956 : case OMP_FAIL_MEMORY_ORDER_RELAXED: return MEMMODEL_RELAXED;
8957 : case OMP_FAIL_MEMORY_ORDER_ACQUIRE: return MEMMODEL_ACQUIRE;
8958 : case OMP_FAIL_MEMORY_ORDER_SEQ_CST: return MEMMODEL_SEQ_CST;
8959 0 : default: gcc_unreachable ();
8960 : }
8961 : }
8962 :
8963 : /* Translate enum omp_memory_order to enum memmodel. The two enums
8964 : are using different numbers so that OMP_MEMORY_ORDER_UNSPECIFIED
8965 : is 0 and omp_memory_order has the fail mode encoded in it too. */
8966 :
8967 : static enum memmodel
8968 10060 : omp_memory_order_to_memmodel (enum omp_memory_order mo)
8969 : {
8970 10060 : enum memmodel ret, fail_ret;
8971 10060 : switch (mo & OMP_MEMORY_ORDER_MASK)
8972 : {
8973 : case OMP_MEMORY_ORDER_RELAXED: ret = MEMMODEL_RELAXED; break;
8974 : case OMP_MEMORY_ORDER_ACQUIRE: ret = MEMMODEL_ACQUIRE; break;
8975 : case OMP_MEMORY_ORDER_RELEASE: ret = MEMMODEL_RELEASE; break;
8976 : case OMP_MEMORY_ORDER_ACQ_REL: ret = MEMMODEL_ACQ_REL; break;
8977 : case OMP_MEMORY_ORDER_SEQ_CST: ret = MEMMODEL_SEQ_CST; break;
8978 0 : default: gcc_unreachable ();
8979 : }
8980 : /* If we drop the -Winvalid-memory-model warning for C++17 P0418R2,
8981 : we can just return ret here unconditionally. Otherwise, work around
8982 : it here and make sure fail memmodel is not stronger. */
8983 10060 : if ((mo & OMP_FAIL_MEMORY_ORDER_MASK) == OMP_FAIL_MEMORY_ORDER_UNSPECIFIED)
8984 : return ret;
8985 142 : fail_ret = omp_memory_order_to_fail_memmodel (mo);
8986 142 : if (fail_ret > ret)
8987 13 : return fail_ret;
8988 : return ret;
8989 : }
8990 :
8991 : /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8992 : operation as a normal volatile load. */
8993 :
8994 : static bool
8995 1183 : expand_omp_atomic_load (basic_block load_bb, tree addr,
8996 : tree loaded_val, int index)
8997 : {
8998 1183 : enum built_in_function tmpbase;
8999 1183 : gimple_stmt_iterator gsi;
9000 1183 : basic_block store_bb;
9001 1183 : location_t loc;
9002 1183 : gimple *stmt;
9003 1183 : tree decl, type, itype;
9004 :
9005 1183 : gsi = gsi_last_nondebug_bb (load_bb);
9006 1183 : stmt = gsi_stmt (gsi);
9007 1183 : gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
9008 1183 : loc = gimple_location (stmt);
9009 :
9010 : /* ??? If the target does not implement atomic_load_optab[mode], and mode
9011 : is smaller than word size, then expand_atomic_load assumes that the load
9012 : is atomic. We could avoid the builtin entirely in this case. */
9013 :
9014 1183 : tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
9015 1183 : decl = builtin_decl_explicit (tmpbase);
9016 1183 : if (decl == NULL_TREE)
9017 : return false;
9018 :
9019 1183 : type = TREE_TYPE (loaded_val);
9020 1183 : itype = TREE_TYPE (TREE_TYPE (decl));
9021 :
9022 1183 : enum omp_memory_order omo = gimple_omp_atomic_memory_order (stmt);
9023 1183 : tree mo = build_int_cst (integer_type_node,
9024 1183 : omp_memory_order_to_memmodel (omo));
9025 1183 : gcall *call = gimple_build_call (decl, 2, addr, mo);
9026 1183 : gimple_set_location (call, loc);
9027 2366 : gimple_set_vuse (call, gimple_vuse (stmt));
9028 1183 : gimple *repl;
9029 1183 : if (!useless_type_conversion_p (type, itype))
9030 : {
9031 1181 : tree lhs = make_ssa_name (itype);
9032 1181 : gimple_call_set_lhs (call, lhs);
9033 1181 : gsi_insert_before (&gsi, call, GSI_SAME_STMT);
9034 1181 : repl = gimple_build_assign (loaded_val,
9035 : build1 (VIEW_CONVERT_EXPR, type, lhs));
9036 1181 : gimple_set_location (repl, loc);
9037 : }
9038 : else
9039 : {
9040 2 : gimple_call_set_lhs (call, loaded_val);
9041 : repl = call;
9042 : }
9043 1183 : gsi_replace (&gsi, repl, true);
9044 :
9045 1183 : store_bb = single_succ (load_bb);
9046 1183 : gsi = gsi_last_nondebug_bb (store_bb);
9047 1183 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
9048 1183 : gsi_remove (&gsi, true);
9049 :
9050 1183 : return true;
9051 : }
9052 :
9053 : /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
9054 : operation as a normal volatile store. */
9055 :
9056 : static bool
9057 856 : expand_omp_atomic_store (basic_block load_bb, tree addr,
9058 : tree loaded_val, tree stored_val, int index)
9059 : {
9060 856 : enum built_in_function tmpbase;
9061 856 : gimple_stmt_iterator gsi;
9062 856 : basic_block store_bb = single_succ (load_bb);
9063 856 : location_t loc;
9064 856 : gimple *stmt;
9065 856 : tree decl, type, itype;
9066 856 : machine_mode imode;
9067 856 : bool exchange;
9068 :
9069 856 : gsi = gsi_last_nondebug_bb (load_bb);
9070 856 : stmt = gsi_stmt (gsi);
9071 856 : gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
9072 :
9073 : /* If the load value is needed, then this isn't a store but an exchange. */
9074 856 : exchange = gimple_omp_atomic_need_value_p (stmt);
9075 :
9076 856 : gsi = gsi_last_nondebug_bb (store_bb);
9077 856 : stmt = gsi_stmt (gsi);
9078 856 : gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
9079 856 : loc = gimple_location (stmt);
9080 :
9081 : /* ??? If the target does not implement atomic_store_optab[mode], and mode
9082 : is smaller than word size, then expand_atomic_store assumes that the store
9083 : is atomic. We could avoid the builtin entirely in this case. */
9084 :
9085 856 : tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
9086 856 : tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
9087 856 : decl = builtin_decl_explicit (tmpbase);
9088 856 : if (decl == NULL_TREE)
9089 : return false;
9090 :
9091 856 : type = TREE_TYPE (stored_val);
9092 :
9093 : /* Dig out the type of the function's second argument. */
9094 856 : itype = TREE_TYPE (decl);
9095 856 : itype = TYPE_ARG_TYPES (itype);
9096 856 : itype = TREE_CHAIN (itype);
9097 856 : itype = TREE_VALUE (itype);
9098 856 : imode = TYPE_MODE (itype);
9099 :
9100 856 : if (exchange && !can_atomic_exchange_p (imode, true))
9101 : return false;
9102 :
9103 856 : if (!useless_type_conversion_p (itype, type))
9104 856 : stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
9105 856 : enum omp_memory_order omo = gimple_omp_atomic_memory_order (stmt);
9106 856 : tree mo = build_int_cst (integer_type_node,
9107 856 : omp_memory_order_to_memmodel (omo));
9108 856 : stored_val = force_gimple_operand_gsi (&gsi, stored_val, true, NULL_TREE,
9109 : true, GSI_SAME_STMT);
9110 856 : gcall *call = gimple_build_call (decl, 3, addr, stored_val, mo);
9111 856 : gimple_set_location (call, loc);
9112 1712 : gimple_set_vuse (call, gimple_vuse (stmt));
9113 1712 : gimple_set_vdef (call, gimple_vdef (stmt));
9114 :
9115 856 : gimple *repl = call;
9116 856 : if (exchange)
9117 : {
9118 88 : if (!useless_type_conversion_p (type, itype))
9119 : {
9120 88 : tree lhs = make_ssa_name (itype);
9121 88 : gimple_call_set_lhs (call, lhs);
9122 88 : gsi_insert_before (&gsi, call, GSI_SAME_STMT);
9123 88 : repl = gimple_build_assign (loaded_val,
9124 : build1 (VIEW_CONVERT_EXPR, type, lhs));
9125 88 : gimple_set_location (repl, loc);
9126 : }
9127 : else
9128 0 : gimple_call_set_lhs (call, loaded_val);
9129 : }
9130 856 : gsi_replace (&gsi, repl, true);
9131 :
9132 : /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
9133 856 : gsi = gsi_last_nondebug_bb (load_bb);
9134 856 : gsi_remove (&gsi, true);
9135 :
9136 856 : return true;
9137 : }
9138 :
9139 : /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
9140 : operation as a __atomic_fetch_op builtin. INDEX is log2 of the
9141 : size of the data type, and thus usable to find the index of the builtin
9142 : decl. Returns false if the expression is not of the proper form. */
9143 :
9144 : static bool
9145 5892 : expand_omp_atomic_fetch_op (basic_block load_bb,
9146 : tree addr, tree loaded_val,
9147 : tree stored_val, int index)
9148 : {
9149 5892 : enum built_in_function oldbase, newbase, tmpbase;
9150 5892 : tree decl, itype, call;
9151 5892 : tree lhs, rhs;
9152 5892 : basic_block store_bb = single_succ (load_bb);
9153 5892 : gimple_stmt_iterator gsi;
9154 5892 : gimple *stmt;
9155 5892 : location_t loc;
9156 5892 : enum tree_code code;
9157 5892 : bool need_old, need_new;
9158 5892 : machine_mode imode;
9159 :
9160 : /* We expect to find the following sequences:
9161 :
9162 : load_bb:
9163 : GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
9164 :
9165 : store_bb:
9166 : val = tmp OP something; (or: something OP tmp)
9167 : GIMPLE_OMP_STORE (val)
9168 :
9169 : ???FIXME: Allow a more flexible sequence.
9170 : Perhaps use data flow to pick the statements.
9171 :
9172 : */
9173 :
9174 5892 : gsi = gsi_after_labels (store_bb);
9175 5892 : stmt = gsi_stmt (gsi);
9176 5892 : if (is_gimple_debug (stmt))
9177 : {
9178 0 : gsi_next_nondebug (&gsi);
9179 0 : if (gsi_end_p (gsi))
9180 : return false;
9181 5892 : stmt = gsi_stmt (gsi);
9182 : }
9183 5892 : loc = gimple_location (stmt);
9184 5892 : if (!is_gimple_assign (stmt))
9185 : return false;
9186 5892 : gsi_next_nondebug (&gsi);
9187 5892 : if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
9188 : return false;
9189 5227 : need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
9190 5227 : need_old = gimple_omp_atomic_need_value_p (last_nondebug_stmt (load_bb));
9191 5227 : enum omp_memory_order omo
9192 5227 : = gimple_omp_atomic_memory_order (last_nondebug_stmt (load_bb));
9193 5227 : enum memmodel mo = omp_memory_order_to_memmodel (omo);
9194 5227 : gcc_checking_assert (!need_old || !need_new);
9195 :
9196 5227 : if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
9197 : return false;
9198 :
9199 : /* Check for one of the supported fetch-op operations. */
9200 5227 : code = gimple_assign_rhs_code (stmt);
9201 5227 : switch (code)
9202 : {
9203 : case PLUS_EXPR:
9204 : case POINTER_PLUS_EXPR:
9205 : oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
9206 : newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
9207 : break;
9208 79 : case MINUS_EXPR:
9209 79 : oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
9210 79 : newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
9211 79 : break;
9212 112 : case BIT_AND_EXPR:
9213 112 : oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
9214 112 : newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
9215 112 : break;
9216 227 : case BIT_IOR_EXPR:
9217 227 : oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
9218 227 : newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
9219 227 : break;
9220 111 : case BIT_XOR_EXPR:
9221 111 : oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
9222 111 : newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
9223 111 : break;
9224 : default:
9225 : return false;
9226 : }
9227 :
9228 : /* Make sure the expression is of the proper form. */
9229 4588 : if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
9230 4406 : rhs = gimple_assign_rhs2 (stmt);
9231 182 : else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
9232 182 : && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
9233 139 : rhs = gimple_assign_rhs1 (stmt);
9234 : else
9235 : return false;
9236 :
9237 9090 : tmpbase = ((enum built_in_function)
9238 4545 : ((need_new ? newbase : oldbase) + index + 1));
9239 4545 : decl = builtin_decl_explicit (tmpbase);
9240 4545 : if (decl == NULL_TREE)
9241 : return false;
9242 4545 : itype = TREE_TYPE (TREE_TYPE (decl));
9243 4545 : imode = TYPE_MODE (itype);
9244 :
9245 : /* We could test all of the various optabs involved, but the fact of the
9246 : matter is that (with the exception of i486 vs i586 and xadd) all targets
9247 : that support any atomic operation optab also implements compare-and-swap.
9248 : Let optabs.cc take care of expanding any compare-and-swap loop. */
9249 4545 : if (!can_compare_and_swap_p (imode, true) || !can_atomic_load_p (imode))
9250 : return false;
9251 :
9252 4541 : gsi = gsi_last_nondebug_bb (load_bb);
9253 4541 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
9254 :
9255 : /* OpenMP does not imply any barrier-like semantics on its atomic ops.
9256 : It only requires that the operation happen atomically. Thus we can
9257 : use the RELAXED memory model. */
9258 4541 : call = build_call_expr_loc (loc, decl, 3, addr,
9259 : fold_convert_loc (loc, itype, rhs),
9260 4541 : build_int_cst (NULL, mo));
9261 :
9262 4541 : if (need_old || need_new)
9263 : {
9264 552 : lhs = need_old ? loaded_val : stored_val;
9265 552 : call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
9266 552 : call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
9267 : }
9268 : else
9269 3989 : call = fold_convert_loc (loc, void_type_node, call);
9270 4541 : force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
9271 4541 : gsi_remove (&gsi, true);
9272 :
9273 4541 : gsi = gsi_last_nondebug_bb (store_bb);
9274 4541 : gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
9275 4541 : gsi_remove (&gsi, true);
9276 4541 : gsi = gsi_last_nondebug_bb (store_bb);
9277 4541 : stmt = gsi_stmt (gsi);
9278 4541 : gsi_remove (&gsi, true);
9279 :
9280 4541 : if (gimple_in_ssa_p (cfun))
9281 29 : release_defs (stmt);
9282 :
9283 : return true;
9284 : }
9285 :
9286 : /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
9287 : compare and exchange as an ATOMIC_COMPARE_EXCHANGE internal function.
9288 : Returns false if the expression is not of the proper form. */
9289 :
9290 : static bool
9291 2217 : expand_omp_atomic_cas (basic_block load_bb, tree addr,
9292 : tree loaded_val, tree stored_val, int index)
9293 : {
9294 : /* We expect to find the following sequences:
9295 :
9296 : load_bb:
9297 : GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
9298 :
9299 : store_bb:
9300 : val = tmp == e ? d : tmp;
9301 : GIMPLE_OMP_ATOMIC_STORE (val)
9302 :
9303 : or in store_bb instead:
9304 : tmp2 = tmp == e;
9305 : val = tmp2 ? d : tmp;
9306 : GIMPLE_OMP_ATOMIC_STORE (val)
9307 :
9308 : or:
9309 : tmp3 = VIEW_CONVERT_EXPR<integral_type>(tmp);
9310 : val = e == tmp3 ? d : tmp;
9311 : GIMPLE_OMP_ATOMIC_STORE (val)
9312 :
9313 : etc. */
9314 :
9315 :
9316 2217 : basic_block store_bb = single_succ (load_bb);
9317 2217 : gimple_stmt_iterator gsi = gsi_last_nondebug_bb (store_bb);
9318 2217 : gimple *store_stmt = gsi_stmt (gsi);
9319 2217 : if (!store_stmt || gimple_code (store_stmt) != GIMPLE_OMP_ATOMIC_STORE)
9320 : return false;
9321 2217 : gsi_prev_nondebug (&gsi);
9322 2217 : if (gsi_end_p (gsi))
9323 : return false;
9324 2211 : gimple *condexpr_stmt = gsi_stmt (gsi);
9325 2211 : if (!is_gimple_assign (condexpr_stmt)
9326 2211 : || gimple_assign_rhs_code (condexpr_stmt) != COND_EXPR)
9327 : return false;
9328 408 : if (!operand_equal_p (gimple_assign_lhs (condexpr_stmt), stored_val, 0))
9329 : return false;
9330 408 : gimple *cond_stmt = NULL;
9331 408 : gimple *vce_stmt = NULL;
9332 408 : gsi_prev_nondebug (&gsi);
9333 408 : if (!gsi_end_p (gsi))
9334 : {
9335 408 : cond_stmt = gsi_stmt (gsi);
9336 408 : if (!is_gimple_assign (cond_stmt))
9337 : return false;
9338 408 : if (gimple_assign_rhs_code (cond_stmt) == EQ_EXPR)
9339 : {
9340 323 : gsi_prev_nondebug (&gsi);
9341 323 : if (!gsi_end_p (gsi))
9342 : {
9343 89 : vce_stmt = gsi_stmt (gsi);
9344 89 : if (!is_gimple_assign (vce_stmt)
9345 89 : || gimple_assign_rhs_code (vce_stmt) != VIEW_CONVERT_EXPR)
9346 : return false;
9347 : }
9348 : }
9349 85 : else if (gimple_assign_rhs_code (cond_stmt) == VIEW_CONVERT_EXPR)
9350 : std::swap (vce_stmt, cond_stmt);
9351 : else
9352 : return false;
9353 69 : if (vce_stmt)
9354 : {
9355 69 : tree vce_rhs = gimple_assign_rhs1 (vce_stmt);
9356 69 : if (TREE_CODE (vce_rhs) != VIEW_CONVERT_EXPR
9357 69 : || !operand_equal_p (TREE_OPERAND (vce_rhs, 0), loaded_val))
9358 : return false;
9359 114 : if (!INTEGRAL_TYPE_P (TREE_TYPE (vce_rhs))
9360 57 : || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (loaded_val))
9361 114 : || !tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vce_rhs)),
9362 57 : TYPE_SIZE (TREE_TYPE (loaded_val))))
9363 : return false;
9364 57 : gsi_prev_nondebug (&gsi);
9365 57 : if (!gsi_end_p (gsi))
9366 : return false;
9367 : }
9368 : }
9369 291 : tree cond = gimple_assign_rhs1 (condexpr_stmt);
9370 291 : tree cond_op1, cond_op2;
9371 291 : if (cond_stmt)
9372 : {
9373 : /* We should now always get a separate cond_stmt. */
9374 291 : if (!operand_equal_p (cond, gimple_assign_lhs (cond_stmt)))
9375 : return false;
9376 291 : cond_op1 = gimple_assign_rhs1 (cond_stmt);
9377 291 : cond_op2 = gimple_assign_rhs2 (cond_stmt);
9378 : }
9379 0 : else if (TREE_CODE (cond) != EQ_EXPR && TREE_CODE (cond) != NE_EXPR)
9380 : return false;
9381 : else
9382 : {
9383 0 : cond_op1 = TREE_OPERAND (cond, 0);
9384 0 : cond_op2 = TREE_OPERAND (cond, 1);
9385 : }
9386 291 : tree d;
9387 291 : if (TREE_CODE (cond) == NE_EXPR)
9388 : {
9389 0 : if (!operand_equal_p (gimple_assign_rhs2 (condexpr_stmt), loaded_val))
9390 : return false;
9391 0 : d = gimple_assign_rhs3 (condexpr_stmt);
9392 : }
9393 291 : else if (!operand_equal_p (gimple_assign_rhs3 (condexpr_stmt), loaded_val))
9394 : return false;
9395 : else
9396 291 : d = gimple_assign_rhs2 (condexpr_stmt);
9397 291 : tree e = vce_stmt ? gimple_assign_lhs (vce_stmt) : loaded_val;
9398 291 : if (operand_equal_p (e, cond_op1))
9399 : e = cond_op2;
9400 21 : else if (operand_equal_p (e, cond_op2))
9401 : e = cond_op1;
9402 : else
9403 : return false;
9404 :
9405 291 : location_t loc = gimple_location (store_stmt);
9406 291 : gimple *load_stmt = last_nondebug_stmt (load_bb);
9407 291 : bool need_new = gimple_omp_atomic_need_value_p (store_stmt);
9408 291 : bool need_old = gimple_omp_atomic_need_value_p (load_stmt);
9409 291 : bool weak = gimple_omp_atomic_weak_p (load_stmt);
9410 291 : enum omp_memory_order omo = gimple_omp_atomic_memory_order (load_stmt);
9411 291 : tree mo = build_int_cst (NULL, omp_memory_order_to_memmodel (omo));
9412 291 : tree fmo = build_int_cst (NULL, omp_memory_order_to_fail_memmodel (omo));
9413 291 : gcc_checking_assert (!need_old || !need_new);
9414 :
9415 291 : enum built_in_function fncode
9416 : = (enum built_in_function) ((int) BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
9417 291 : + index + 1);
9418 291 : tree cmpxchg = builtin_decl_explicit (fncode);
9419 291 : if (cmpxchg == NULL_TREE)
9420 : return false;
9421 291 : tree itype = TREE_TYPE (TREE_TYPE (cmpxchg));
9422 :
9423 291 : if (!can_compare_and_swap_p (TYPE_MODE (itype), true)
9424 291 : || !can_atomic_load_p (TYPE_MODE (itype)))
9425 : return false;
9426 :
9427 290 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (loaded_val));
9428 290 : if (SCALAR_FLOAT_TYPE_P (type) && !vce_stmt)
9429 : return false;
9430 :
9431 289 : gsi = gsi_for_stmt (store_stmt);
9432 289 : if (!useless_type_conversion_p (itype, TREE_TYPE (e)))
9433 : {
9434 232 : tree ne = create_tmp_reg (itype);
9435 232 : gimple *g = gimple_build_assign (ne, NOP_EXPR, e);
9436 232 : gimple_set_location (g, loc);
9437 232 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9438 232 : e = ne;
9439 : }
9440 289 : if (!useless_type_conversion_p (itype, TREE_TYPE (d)))
9441 : {
9442 289 : tree nd = create_tmp_reg (itype);
9443 289 : enum tree_code code;
9444 289 : if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (d)))
9445 : {
9446 57 : code = VIEW_CONVERT_EXPR;
9447 57 : d = build1 (VIEW_CONVERT_EXPR, itype, d);
9448 : }
9449 : else
9450 : code = NOP_EXPR;
9451 289 : gimple *g = gimple_build_assign (nd, code, d);
9452 289 : gimple_set_location (g, loc);
9453 289 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9454 289 : d = nd;
9455 : }
9456 :
9457 289 : tree ctype = build_complex_type (itype);
9458 289 : int flag = int_size_in_bytes (itype) + (weak ? 256 : 0);
9459 289 : gimple *g
9460 289 : = gimple_build_call_internal (IFN_ATOMIC_COMPARE_EXCHANGE, 6, addr, e, d,
9461 289 : build_int_cst (integer_type_node, flag),
9462 : mo, fmo);
9463 289 : tree cres = create_tmp_reg (ctype);
9464 289 : gimple_call_set_lhs (g, cres);
9465 289 : gimple_set_location (g, loc);
9466 289 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9467 :
9468 289 : if (cond_stmt || need_old || need_new)
9469 : {
9470 289 : tree im = create_tmp_reg (itype);
9471 289 : g = gimple_build_assign (im, IMAGPART_EXPR,
9472 : build1 (IMAGPART_EXPR, itype, cres));
9473 289 : gimple_set_location (g, loc);
9474 289 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9475 :
9476 289 : tree re = NULL_TREE;
9477 289 : if (need_old || need_new)
9478 : {
9479 199 : re = create_tmp_reg (itype);
9480 199 : g = gimple_build_assign (re, REALPART_EXPR,
9481 : build1 (REALPART_EXPR, itype, cres));
9482 199 : gimple_set_location (g, loc);
9483 199 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9484 : }
9485 :
9486 289 : if (cond_stmt)
9487 : {
9488 289 : g = gimple_build_assign (cond, NOP_EXPR, im);
9489 289 : gimple_set_location (g, loc);
9490 289 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9491 : }
9492 :
9493 289 : if (need_new)
9494 : {
9495 44 : g = gimple_build_assign (create_tmp_reg (itype), COND_EXPR,
9496 : cond_stmt
9497 0 : ? cond : build2 (NE_EXPR, boolean_type_node,
9498 : im, build_zero_cst (itype)),
9499 : d, re);
9500 44 : gimple_set_location (g, loc);
9501 44 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9502 44 : re = gimple_assign_lhs (g);
9503 : }
9504 :
9505 289 : if (need_old || need_new)
9506 : {
9507 199 : tree v = need_old ? loaded_val : stored_val;
9508 199 : enum tree_code code;
9509 199 : if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (v)))
9510 : {
9511 38 : code = VIEW_CONVERT_EXPR;
9512 38 : re = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (v), re);
9513 : }
9514 161 : else if (!useless_type_conversion_p (TREE_TYPE (v), itype))
9515 : code = NOP_EXPR;
9516 : else
9517 0 : code = TREE_CODE (re);
9518 199 : g = gimple_build_assign (v, code, re);
9519 199 : gimple_set_location (g, loc);
9520 199 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9521 : }
9522 : }
9523 :
9524 289 : gsi_remove (&gsi, true);
9525 289 : gsi = gsi_for_stmt (load_stmt);
9526 289 : gsi_remove (&gsi, true);
9527 289 : gsi = gsi_for_stmt (condexpr_stmt);
9528 289 : gsi_remove (&gsi, true);
9529 289 : if (cond_stmt)
9530 : {
9531 289 : gsi = gsi_for_stmt (cond_stmt);
9532 289 : gsi_remove (&gsi, true);
9533 : }
9534 289 : if (vce_stmt)
9535 : {
9536 57 : gsi = gsi_for_stmt (vce_stmt);
9537 57 : gsi_remove (&gsi, true);
9538 : }
9539 :
9540 : return true;
9541 : }
9542 :
9543 : /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
9544 :
9545 : oldval = *addr;
9546 : repeat:
9547 : newval = rhs; // with oldval replacing *addr in rhs
9548 : oldval = __sync_val_compare_and_swap (addr, oldval, newval);
9549 : if (oldval != newval)
9550 : goto repeat;
9551 :
9552 : INDEX is log2 of the size of the data type, and thus usable to find the
9553 : index of the builtin decl. */
9554 :
9555 : static bool
9556 2586 : expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
9557 : tree addr, tree loaded_val, tree stored_val,
9558 : int index)
9559 : {
9560 2586 : tree loadedi, storedi, initial, new_storedi, old_vali;
9561 2586 : tree type, itype, cmpxchg, iaddr, atype;
9562 2586 : gimple_stmt_iterator si;
9563 2586 : basic_block loop_header = single_succ (load_bb);
9564 2586 : gimple *phi, *stmt;
9565 2586 : edge e;
9566 2586 : enum built_in_function fncode;
9567 :
9568 2586 : fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
9569 2586 : + index + 1);
9570 2586 : cmpxchg = builtin_decl_explicit (fncode);
9571 2586 : if (cmpxchg == NULL_TREE)
9572 : return false;
9573 2586 : type = TYPE_MAIN_VARIANT (TREE_TYPE (loaded_val));
9574 2586 : atype = type;
9575 2586 : itype = TREE_TYPE (TREE_TYPE (cmpxchg));
9576 :
9577 2586 : if (!can_compare_and_swap_p (TYPE_MODE (itype), true)
9578 2586 : || !can_atomic_load_p (TYPE_MODE (itype)))
9579 : return false;
9580 :
9581 : /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
9582 2503 : si = gsi_last_nondebug_bb (load_bb);
9583 2503 : gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
9584 2503 : location_t loc = gimple_location (gsi_stmt (si));
9585 2503 : enum omp_memory_order omo = gimple_omp_atomic_memory_order (gsi_stmt (si));
9586 2503 : tree mo = build_int_cst (NULL, omp_memory_order_to_memmodel (omo));
9587 2503 : tree fmo = build_int_cst (NULL, omp_memory_order_to_fail_memmodel (omo));
9588 :
9589 : /* For floating-point values, we'll need to view-convert them to integers
9590 : so that we can perform the atomic compare and swap. Simplify the
9591 : following code by always setting up the "i"ntegral variables. */
9592 2503 : if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
9593 : {
9594 845 : tree iaddr_val;
9595 :
9596 845 : iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
9597 : true));
9598 845 : atype = itype;
9599 845 : iaddr_val
9600 845 : = force_gimple_operand_gsi (&si,
9601 845 : fold_convert (TREE_TYPE (iaddr), addr),
9602 : false, NULL_TREE, true, GSI_SAME_STMT);
9603 845 : stmt = gimple_build_assign (iaddr, iaddr_val);
9604 845 : gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9605 845 : loadedi = create_tmp_var (itype);
9606 845 : if (gimple_in_ssa_p (cfun))
9607 15 : loadedi = make_ssa_name (loadedi);
9608 : }
9609 : else
9610 : {
9611 : iaddr = addr;
9612 : loadedi = loaded_val;
9613 : }
9614 :
9615 2503 : fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
9616 2503 : tree loaddecl = builtin_decl_explicit (fncode);
9617 2503 : if (loaddecl)
9618 2503 : initial
9619 2503 : = fold_convert (atype,
9620 : build_call_expr (loaddecl, 2, iaddr,
9621 : build_int_cst (NULL_TREE,
9622 : MEMMODEL_RELAXED)));
9623 : else
9624 : {
9625 0 : tree off
9626 0 : = build_int_cst (build_pointer_type_for_mode (atype, ptr_mode,
9627 : true), 0);
9628 0 : initial = build2 (MEM_REF, atype, iaddr, off);
9629 : }
9630 :
9631 2503 : initial
9632 2503 : = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
9633 : GSI_SAME_STMT);
9634 :
9635 : /* Move the value to the LOADEDI temporary. */
9636 2503 : if (gimple_in_ssa_p (cfun))
9637 : {
9638 39 : gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
9639 39 : phi = create_phi_node (loadedi, loop_header);
9640 39 : SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
9641 : initial);
9642 : }
9643 : else
9644 2464 : gsi_insert_before (&si,
9645 2464 : gimple_build_assign (loadedi, initial),
9646 : GSI_SAME_STMT);
9647 2503 : if (loadedi != loaded_val)
9648 : {
9649 845 : gimple_stmt_iterator gsi2;
9650 845 : tree x;
9651 :
9652 845 : x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
9653 845 : gsi2 = gsi_start_bb (loop_header);
9654 845 : if (gimple_in_ssa_p (cfun))
9655 : {
9656 15 : gassign *stmt;
9657 15 : x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
9658 : true, GSI_SAME_STMT);
9659 15 : stmt = gimple_build_assign (loaded_val, x);
9660 15 : gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
9661 : }
9662 : else
9663 : {
9664 830 : x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
9665 830 : force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
9666 : true, GSI_SAME_STMT);
9667 : }
9668 : }
9669 2503 : gsi_remove (&si, true);
9670 :
9671 2503 : si = gsi_last_nondebug_bb (store_bb);
9672 2503 : gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
9673 :
9674 2503 : if (iaddr == addr)
9675 : storedi = stored_val;
9676 : else
9677 845 : storedi
9678 845 : = force_gimple_operand_gsi (&si,
9679 : build1 (VIEW_CONVERT_EXPR, itype,
9680 : stored_val), true, NULL_TREE, true,
9681 : GSI_SAME_STMT);
9682 :
9683 : /* Build the compare&swap statement. */
9684 2503 : tree ctype = build_complex_type (itype);
9685 2503 : int flag = int_size_in_bytes (itype);
9686 2503 : new_storedi = build_call_expr_internal_loc (loc, IFN_ATOMIC_COMPARE_EXCHANGE,
9687 : ctype, 6, iaddr, loadedi,
9688 : storedi,
9689 : build_int_cst (integer_type_node,
9690 2503 : flag),
9691 : mo, fmo);
9692 2503 : new_storedi = build1 (REALPART_EXPR, itype, new_storedi);
9693 2503 : new_storedi = force_gimple_operand_gsi (&si,
9694 2503 : fold_convert (TREE_TYPE (loadedi),
9695 : new_storedi),
9696 : true, NULL_TREE,
9697 : true, GSI_SAME_STMT);
9698 :
9699 2503 : if (gimple_in_ssa_p (cfun))
9700 : old_vali = loadedi;
9701 : else
9702 : {
9703 2464 : old_vali = create_tmp_var (TREE_TYPE (loadedi));
9704 2464 : stmt = gimple_build_assign (old_vali, loadedi);
9705 2464 : gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9706 :
9707 2464 : stmt = gimple_build_assign (loadedi, new_storedi);
9708 2464 : gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9709 : }
9710 :
9711 : /* Note that we always perform the comparison as an integer, even for
9712 : floating point. This allows the atomic operation to properly
9713 : succeed even with NaNs and -0.0. */
9714 2503 : tree ne = build2 (NE_EXPR, boolean_type_node, new_storedi, old_vali);
9715 2503 : stmt = gimple_build_cond_empty (ne);
9716 2503 : gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9717 :
9718 : /* Update cfg. */
9719 2503 : e = single_succ_edge (store_bb);
9720 2503 : e->flags &= ~EDGE_FALLTHRU;
9721 2503 : e->flags |= EDGE_FALSE_VALUE;
9722 : /* Expect no looping. */
9723 2503 : e->probability = profile_probability::guessed_always ();
9724 :
9725 2503 : e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
9726 2503 : e->probability = profile_probability::guessed_never ();
9727 :
9728 : /* Copy the new value to loadedi (we already did that before the condition
9729 : if we are not in SSA). */
9730 2503 : if (gimple_in_ssa_p (cfun))
9731 : {
9732 39 : phi = gimple_seq_first_stmt (phi_nodes (loop_header));
9733 39 : SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
9734 : }
9735 :
9736 : /* Remove GIMPLE_OMP_ATOMIC_STORE. */
9737 2503 : stmt = gsi_stmt (si);
9738 2503 : gsi_remove (&si, true);
9739 2503 : if (gimple_in_ssa_p (cfun))
9740 39 : release_defs (stmt);
9741 :
9742 2503 : class loop *loop = alloc_loop ();
9743 2503 : loop->header = loop_header;
9744 2503 : loop->latch = store_bb;
9745 2503 : add_loop (loop, loop_header->loop_father);
9746 :
9747 2503 : return true;
9748 : }
9749 :
9750 : /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
9751 :
9752 : GOMP_atomic_start ();
9753 : *addr = rhs;
9754 : GOMP_atomic_end ();
9755 :
9756 : The result is not globally atomic, but works so long as all parallel
9757 : references are within #pragma omp atomic directives. According to
9758 : responses received from omp@openmp.org, appears to be within spec.
9759 : Which makes sense, since that's how several other compilers handle
9760 : this situation as well.
9761 : LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
9762 : expanding. STORED_VAL is the operand of the matching
9763 : GIMPLE_OMP_ATOMIC_STORE.
9764 :
9765 : We replace
9766 : GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
9767 : loaded_val = *addr;
9768 :
9769 : and replace
9770 : GIMPLE_OMP_ATOMIC_STORE (stored_val) with
9771 : *addr = stored_val;
9772 : */
9773 :
9774 : static bool
9775 293 : expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
9776 : tree addr, tree loaded_val, tree stored_val)
9777 : {
9778 293 : gimple_stmt_iterator si;
9779 293 : gassign *stmt;
9780 293 : tree t;
9781 :
9782 293 : si = gsi_last_nondebug_bb (load_bb);
9783 293 : gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
9784 :
9785 293 : t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
9786 293 : t = build_call_expr (t, 0);
9787 293 : force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
9788 :
9789 293 : tree mem = build_simple_mem_ref (addr);
9790 293 : TREE_TYPE (mem) = TREE_TYPE (loaded_val);
9791 293 : TREE_OPERAND (mem, 1)
9792 293 : = fold_convert (build_pointer_type_for_mode (TREE_TYPE (mem), ptr_mode,
9793 : true),
9794 : TREE_OPERAND (mem, 1));
9795 293 : stmt = gimple_build_assign (loaded_val, mem);
9796 293 : gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9797 293 : gsi_remove (&si, true);
9798 :
9799 293 : si = gsi_last_nondebug_bb (store_bb);
9800 293 : gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
9801 :
9802 293 : stmt = gimple_build_assign (unshare_expr (mem), stored_val);
9803 586 : gimple_set_vuse (stmt, gimple_vuse (gsi_stmt (si)));
9804 586 : gimple_set_vdef (stmt, gimple_vdef (gsi_stmt (si)));
9805 293 : gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9806 :
9807 293 : t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
9808 293 : t = build_call_expr (t, 0);
9809 293 : force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
9810 293 : gsi_remove (&si, true);
9811 293 : return true;
9812 : }
9813 :
9814 : /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
9815 : using expand_omp_atomic_fetch_op. If it failed, we try to
9816 : call expand_omp_atomic_pipeline, and if it fails too, the
9817 : ultimate fallback is wrapping the operation in a mutex
9818 : (expand_omp_atomic_mutex). REGION is the atomic region built
9819 : by build_omp_regions_1(). */
9820 :
9821 : static void
9822 9665 : expand_omp_atomic (struct omp_region *region)
9823 : {
9824 9665 : basic_block load_bb = region->entry, store_bb = region->exit;
9825 9665 : gomp_atomic_load *load
9826 9665 : = as_a <gomp_atomic_load *> (last_nondebug_stmt (load_bb));
9827 9665 : gomp_atomic_store *store
9828 9665 : = as_a <gomp_atomic_store *> (last_nondebug_stmt (store_bb));
9829 9665 : tree loaded_val = gimple_omp_atomic_load_lhs (load);
9830 9665 : tree addr = gimple_omp_atomic_load_rhs (load);
9831 9665 : tree stored_val = gimple_omp_atomic_store_val (store);
9832 9665 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (loaded_val));
9833 9665 : HOST_WIDE_INT index;
9834 :
9835 : /* Make sure the type is one of the supported sizes. */
9836 9665 : index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
9837 9665 : index = exact_log2 (index);
9838 9631 : if (index >= 0 && index <= 4)
9839 : {
9840 9631 : unsigned int align = TYPE_ALIGN_UNIT (type);
9841 :
9842 : /* __sync builtins require strict data alignment. */
9843 19262 : if (exact_log2 (align) >= index)
9844 : {
9845 : /* Atomic load. */
9846 9455 : scalar_mode smode;
9847 9455 : if (loaded_val == stored_val
9848 1187 : && (is_int_mode (TYPE_MODE (type), &smode)
9849 1337 : || is_float_mode (TYPE_MODE (type), &smode))
9850 1187 : && GET_MODE_BITSIZE (smode) <= BITS_PER_WORD
9851 10638 : && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
9852 9665 : return;
9853 :
9854 : /* Atomic store. */
9855 8272 : if ((is_int_mode (TYPE_MODE (type), &smode)
9856 9317 : || is_float_mode (TYPE_MODE (type), &smode))
9857 8272 : && GET_MODE_BITSIZE (smode) <= BITS_PER_WORD
9858 8189 : && store_bb == single_succ (load_bb)
9859 7574 : && first_stmt (store_bb) == store
9860 856 : && expand_omp_atomic_store (load_bb, addr, loaded_val,
9861 : stored_val, index))
9862 : return;
9863 :
9864 : /* When possible, use specialized atomic update functions. */
9865 985 : if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
9866 6439 : && store_bb == single_succ (load_bb)
9867 13308 : && expand_omp_atomic_fetch_op (load_bb, addr,
9868 : loaded_val, stored_val, index))
9869 : return;
9870 :
9871 : /* When possible, use ATOMIC_COMPARE_EXCHANGE ifn without a loop. */
9872 2875 : if (store_bb == single_succ (load_bb)
9873 2256 : && !gimple_in_ssa_p (cfun)
9874 5092 : && expand_omp_atomic_cas (load_bb, addr, loaded_val, stored_val,
9875 : index))
9876 : return;
9877 :
9878 : /* If we don't have specialized __sync builtins, try and implement
9879 : as a compare and swap loop. */
9880 2586 : if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
9881 : loaded_val, stored_val, index))
9882 : return;
9883 : }
9884 : }
9885 :
9886 : /* The ultimate fallback is wrapping the operation in a mutex. */
9887 293 : expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
9888 : }
9889 :
9890 : /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
9891 : at REGION_EXIT. */
9892 :
9893 : static void
9894 1651 : mark_loops_in_oacc_kernels_region (basic_block region_entry,
9895 : basic_block region_exit)
9896 : {
9897 1651 : class loop *outer = region_entry->loop_father;
9898 1651 : gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
9899 :
9900 : /* Don't parallelize the kernels region if it contains more than one outer
9901 : loop. */
9902 1651 : unsigned int nr_outer_loops = 0;
9903 1651 : class loop *single_outer = NULL;
9904 33062 : for (class loop *loop = outer->inner; loop != NULL; loop = loop->next)
9905 : {
9906 31411 : gcc_assert (loop_outer (loop) == outer);
9907 :
9908 31411 : if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
9909 23379 : continue;
9910 :
9911 14588 : if (region_exit != NULL
9912 8032 : && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
9913 6556 : continue;
9914 :
9915 1476 : nr_outer_loops++;
9916 1476 : single_outer = loop;
9917 : }
9918 1651 : if (nr_outer_loops != 1)
9919 : return;
9920 :
9921 1336 : for (class loop *loop = single_outer->inner;
9922 2293 : loop != NULL;
9923 957 : loop = loop->inner)
9924 1045 : if (loop->next)
9925 : return;
9926 :
9927 : /* Mark the loops in the region. */
9928 3269 : for (class loop *loop = single_outer; loop != NULL; loop = loop->inner)
9929 2021 : loop->in_oacc_kernels_region = true;
9930 : }
9931 :
9932 : /* Build target argument identifier from the DEVICE identifier, value
9933 : identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
9934 :
9935 : static tree
9936 23580 : get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
9937 : {
9938 23580 : tree t = build_int_cst (integer_type_node, device);
9939 23580 : if (subseqent_param)
9940 672 : t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
9941 : build_int_cst (integer_type_node,
9942 : GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
9943 23580 : t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
9944 : build_int_cst (integer_type_node, id));
9945 23580 : return t;
9946 : }
9947 :
9948 : /* Like above but return it in type that can be directly stored as an element
9949 : of the argument array. */
9950 :
9951 : static tree
9952 672 : get_target_argument_identifier (int device, bool subseqent_param, int id)
9953 : {
9954 672 : tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
9955 672 : return fold_convert (ptr_type_node, t);
9956 : }
9957 :
9958 : /* Return a target argument consisting of DEVICE identifier, value identifier
9959 : ID, and the actual VALUE. */
9960 :
9961 : static tree
9962 22908 : get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
9963 : tree value)
9964 : {
9965 22908 : tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
9966 : fold_convert (integer_type_node, value),
9967 : build_int_cst (unsigned_type_node,
9968 : GOMP_TARGET_ARG_VALUE_SHIFT));
9969 22908 : t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
9970 : get_target_argument_identifier_1 (device, false, id));
9971 22908 : t = fold_convert (ptr_type_node, t);
9972 22908 : return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
9973 : }
9974 :
9975 : /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
9976 : push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
9977 : otherwise push an identifier (with DEVICE and ID) and the VALUE in two
9978 : arguments. */
9979 :
9980 : static void
9981 23580 : push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
9982 : int id, tree value, vec <tree> *args)
9983 : {
9984 23580 : if (tree_fits_shwi_p (value)
9985 22908 : && tree_to_shwi (value) > -(1 << 15)
9986 22908 : && tree_to_shwi (value) < (1 << 15))
9987 22908 : args->quick_push (get_target_argument_value (gsi, device, id, value));
9988 : else
9989 : {
9990 672 : args->quick_push (get_target_argument_identifier (device, true, id));
9991 672 : value = fold_convert (ptr_type_node, value);
9992 672 : value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
9993 : GSI_SAME_STMT);
9994 672 : args->quick_push (value);
9995 : }
9996 23580 : }
9997 :
9998 : /* Create an array of arguments that is then passed to GOMP_target. */
9999 :
10000 : static tree
10001 11790 : get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
10002 : {
10003 11790 : auto_vec <tree, 6> args;
10004 11790 : tree clauses = gimple_omp_target_clauses (tgt_stmt);
10005 11790 : tree num_teams = omp_find_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
10006 11790 : tree thread_limit = omp_find_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
10007 11790 : tree message = omp_find_clause (clauses, OMP_CLAUSE_MESSAGE);
10008 11790 : if (message)
10009 : /* FIXME: error termination checking also requires to check
10010 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR not only UPPER, i.e. it
10011 : needs to be passed to the runtime! Note that both target and
10012 : a nested teams can have a 'message' clause - and both take a
10013 : thread_limit clause. */
10014 1 : sorry_at (OMP_CLAUSE_LOCATION (message), "%<message%> clause");
10015 11790 : if (num_teams)
10016 : {
10017 11790 : tree expr = OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (num_teams);
10018 : /* FIXME: Update omp-low.cc's lower_omp_teams when implementing. */
10019 11790 : if (TREE_CODE (expr) == TREE_LIST
10020 0 : && OMP_CLAUSE_NUM_TEAMS_DIMS (num_teams)
10021 11790 : && TREE_CHAIN (expr))
10022 : {
10023 0 : sorry_at (OMP_CLAUSE_LOCATION (num_teams),
10024 : "%<num_teams%> clause with %<dims%> modifier");
10025 0 : num_teams = TREE_VALUE (expr);
10026 : }
10027 11790 : else if (TREE_CODE (expr) == TREE_LIST)
10028 0 : num_teams = (TREE_CHAIN (expr)
10029 0 : ? TREE_VALUE (TREE_CHAIN (expr)) : TREE_VALUE (expr));
10030 : else
10031 : num_teams = expr;
10032 : }
10033 : else
10034 0 : num_teams = integer_minus_one_node;
10035 11790 : push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
10036 : GOMP_TARGET_ARG_NUM_TEAMS,
10037 : num_teams, &args);
10038 11790 : if (thread_limit)
10039 : {
10040 11790 : tree expr = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10041 11790 : if (TREE_CODE (expr) == TREE_LIST)
10042 : {
10043 43 : if (OMP_CLAUSE_THREAD_LIMIT_DIMS (thread_limit)
10044 43 : && (TREE_CHAIN (expr)
10045 1 : || OMP_CLAUSE_THREAD_LIMIT_STRICT (thread_limit)))
10046 1 : sorry_at (OMP_CLAUSE_LOCATION (thread_limit),
10047 : "%<thread_limit%> clause with %<dims%> modifier");
10048 42 : else if (OMP_CLAUSE_THREAD_LIMIT_STRICT (thread_limit))
10049 0 : sorry_at (OMP_CLAUSE_LOCATION (thread_limit),
10050 : "%<thread_limit%> clause with %<strict%> modifier");
10051 43 : expr = TREE_VALUE (expr);
10052 : }
10053 11747 : else if (OMP_CLAUSE_THREAD_LIMIT_STRICT (thread_limit))
10054 0 : sorry_at (OMP_CLAUSE_LOCATION (thread_limit),
10055 : "%<thread_limit%> clause with %<strict%> modifier");
10056 : thread_limit = expr;
10057 : }
10058 : else
10059 0 : thread_limit = integer_minus_one_node;
10060 11790 : push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
10061 : GOMP_TARGET_ARG_THREAD_LIMIT,
10062 : thread_limit, &args);
10063 :
10064 : /* Produce more, perhaps device specific, arguments here. */
10065 :
10066 23580 : tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
10067 11790 : args.length () + 1),
10068 : ".omp_target_args");
10069 36042 : for (unsigned i = 0; i < args.length (); i++)
10070 : {
10071 24252 : tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
10072 24252 : build_int_cst (integer_type_node, i),
10073 : NULL_TREE, NULL_TREE);
10074 24252 : gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
10075 : GSI_SAME_STMT);
10076 : }
10077 23580 : tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
10078 11790 : build_int_cst (integer_type_node, args.length ()),
10079 : NULL_TREE, NULL_TREE);
10080 11790 : gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
10081 : GSI_SAME_STMT);
10082 11790 : TREE_ADDRESSABLE (argarray) = 1;
10083 11790 : return build_fold_addr_expr (argarray);
10084 11790 : }
10085 :
10086 : /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
10087 :
10088 : static void
10089 37153 : expand_omp_target (struct omp_region *region)
10090 : {
10091 37153 : basic_block entry_bb, exit_bb, new_bb;
10092 37153 : struct function *child_cfun;
10093 37153 : tree child_fn, child_fn2, block, t, c;
10094 37153 : gimple_stmt_iterator gsi;
10095 37153 : gomp_target *entry_stmt;
10096 37153 : gimple *stmt;
10097 37153 : edge e;
10098 37153 : bool offloaded;
10099 37153 : int target_kind;
10100 :
10101 37153 : entry_stmt = as_a <gomp_target *> (last_nondebug_stmt (region->entry));
10102 37153 : target_kind = gimple_omp_target_kind (entry_stmt);
10103 37153 : new_bb = region->entry;
10104 :
10105 37153 : offloaded = is_gimple_omp_offloaded (entry_stmt);
10106 37153 : switch (target_kind)
10107 : {
10108 37153 : case GF_OMP_TARGET_KIND_REGION:
10109 37153 : case GF_OMP_TARGET_KIND_UPDATE:
10110 37153 : case GF_OMP_TARGET_KIND_ENTER_DATA:
10111 37153 : case GF_OMP_TARGET_KIND_EXIT_DATA:
10112 37153 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
10113 37153 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
10114 37153 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
10115 37153 : case GF_OMP_TARGET_KIND_OACC_UPDATE:
10116 37153 : case GF_OMP_TARGET_KIND_OACC_ENTER_DATA:
10117 37153 : case GF_OMP_TARGET_KIND_OACC_EXIT_DATA:
10118 37153 : case GF_OMP_TARGET_KIND_OACC_DECLARE:
10119 37153 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
10120 37153 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
10121 37153 : case GF_OMP_TARGET_KIND_DATA:
10122 37153 : case GF_OMP_TARGET_KIND_OACC_DATA:
10123 37153 : case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
10124 37153 : case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
10125 37153 : break;
10126 0 : default:
10127 0 : gcc_unreachable ();
10128 : }
10129 :
10130 37153 : tree clauses = gimple_omp_target_clauses (entry_stmt);
10131 :
10132 37153 : bool is_ancestor = false;
10133 37153 : bool is_host_only = false;
10134 37153 : child_fn = child_fn2 = NULL_TREE;
10135 37153 : child_cfun = NULL;
10136 37153 : if (offloaded)
10137 : {
10138 21185 : c = omp_find_clause (clauses, OMP_CLAUSE_DEVICE);
10139 21185 : if (ENABLE_OFFLOADING && c)
10140 : is_ancestor = OMP_CLAUSE_DEVICE_ANCESTOR (c);
10141 21185 : c = omp_find_clause (clauses, OMP_CLAUSE_DEVICE_TYPE);
10142 21185 : if (c && OMP_CLAUSE_DEVICE_TYPE_KIND (c) == OMP_CLAUSE_DEVICE_TYPE_HOST)
10143 : is_host_only = true;
10144 21185 : child_fn = gimple_omp_target_child_fn (entry_stmt);
10145 21185 : child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10146 : }
10147 :
10148 : /* Supported by expand_omp_taskreg, but not here. */
10149 21185 : if (child_cfun != NULL)
10150 21185 : gcc_checking_assert (!child_cfun->cfg);
10151 37153 : gcc_checking_assert (!gimple_in_ssa_p (cfun));
10152 :
10153 37153 : entry_bb = region->entry;
10154 37153 : exit_bb = region->exit;
10155 :
10156 37153 : if (target_kind == GF_OMP_TARGET_KIND_OACC_KERNELS)
10157 1651 : mark_loops_in_oacc_kernels_region (region->entry, region->exit);
10158 :
10159 : /* Going on, all OpenACC compute constructs are mapped to
10160 : 'BUILT_IN_GOACC_PARALLEL', and get their compute regions outlined.
10161 : To distinguish between them, we attach attributes. */
10162 37153 : switch (target_kind)
10163 : {
10164 6825 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
10165 6825 : DECL_ATTRIBUTES (child_fn)
10166 6825 : = tree_cons (get_identifier ("oacc parallel"),
10167 6825 : NULL_TREE, DECL_ATTRIBUTES (child_fn));
10168 6825 : break;
10169 1651 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
10170 1651 : DECL_ATTRIBUTES (child_fn)
10171 1651 : = tree_cons (get_identifier ("oacc kernels"),
10172 1651 : NULL_TREE, DECL_ATTRIBUTES (child_fn));
10173 1651 : break;
10174 756 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
10175 756 : DECL_ATTRIBUTES (child_fn)
10176 756 : = tree_cons (get_identifier ("oacc serial"),
10177 756 : NULL_TREE, DECL_ATTRIBUTES (child_fn));
10178 756 : break;
10179 54 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
10180 54 : DECL_ATTRIBUTES (child_fn)
10181 54 : = tree_cons (get_identifier ("oacc parallel_kernels_parallelized"),
10182 54 : NULL_TREE, DECL_ATTRIBUTES (child_fn));
10183 54 : break;
10184 109 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
10185 109 : DECL_ATTRIBUTES (child_fn)
10186 109 : = tree_cons (get_identifier ("oacc parallel_kernels_gang_single"),
10187 109 : NULL_TREE, DECL_ATTRIBUTES (child_fn));
10188 109 : break;
10189 27758 : default:
10190 : /* Make sure we don't miss any. */
10191 27758 : gcc_checking_assert (!(is_gimple_omp_oacc (entry_stmt)
10192 : && is_gimple_omp_offloaded (entry_stmt)));
10193 : break;
10194 : }
10195 :
10196 37153 : if (offloaded)
10197 : {
10198 21185 : unsigned srcidx, dstidx, num;
10199 :
10200 : /* If the offloading region needs data sent from the parent
10201 : function, then the very first statement (except possible
10202 : tree profile counter updates) of the offloading body
10203 : is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
10204 : &.OMP_DATA_O is passed as an argument to the child function,
10205 : we need to replace it with the argument as seen by the child
10206 : function.
10207 :
10208 : In most cases, this will end up being the identity assignment
10209 : .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
10210 : a function call that has been inlined, the original PARM_DECL
10211 : .OMP_DATA_I may have been converted into a different local
10212 : variable. In which case, we need to keep the assignment. */
10213 21185 : tree data_arg = gimple_omp_target_data_arg (entry_stmt);
10214 21185 : if (data_arg)
10215 : {
10216 16531 : basic_block entry_succ_bb = single_succ (entry_bb);
10217 16531 : gimple_stmt_iterator gsi;
10218 16531 : tree arg;
10219 16531 : gimple *tgtcopy_stmt = NULL;
10220 16531 : tree sender = TREE_VEC_ELT (data_arg, 0);
10221 :
10222 33062 : for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
10223 : {
10224 16531 : gcc_assert (!gsi_end_p (gsi));
10225 16531 : stmt = gsi_stmt (gsi);
10226 16531 : if (gimple_code (stmt) != GIMPLE_ASSIGN)
10227 0 : continue;
10228 :
10229 16531 : if (gimple_num_ops (stmt) == 2)
10230 : {
10231 16531 : tree arg = gimple_assign_rhs1 (stmt);
10232 :
10233 : /* We're ignoring the subcode because we're
10234 : effectively doing a STRIP_NOPS. */
10235 :
10236 16531 : if ((TREE_CODE (arg) == ADDR_EXPR
10237 16424 : && TREE_OPERAND (arg, 0) == sender)
10238 16531 : || arg == sender)
10239 : {
10240 16531 : tgtcopy_stmt = stmt;
10241 16531 : break;
10242 : }
10243 : }
10244 0 : }
10245 :
10246 16531 : gcc_assert (tgtcopy_stmt != NULL);
10247 16531 : arg = DECL_ARGUMENTS (child_fn);
10248 :
10249 16531 : gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
10250 16531 : gsi_remove (&gsi, true);
10251 : }
10252 :
10253 : /* Declare local variables needed in CHILD_CFUN. */
10254 21185 : block = DECL_INITIAL (child_fn);
10255 21185 : BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
10256 : /* The gimplifier could record temporaries in the offloading block
10257 : rather than in containing function's local_decls chain,
10258 : which would mean cgraph missed finalizing them. Do it now. */
10259 158408 : for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
10260 137223 : if (VAR_P (t) && TREE_STATIC (t) && !DECL_EXTERNAL (t))
10261 0 : varpool_node::finalize_decl (t);
10262 21185 : DECL_SAVED_TREE (child_fn) = NULL;
10263 : /* We'll create a CFG for child_fn, so no gimple body is needed. */
10264 21185 : gimple_set_body (child_fn, NULL);
10265 21185 : TREE_USED (block) = 1;
10266 :
10267 : /* Reset DECL_CONTEXT on function arguments. */
10268 42370 : for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10269 21185 : DECL_CONTEXT (t) = child_fn;
10270 :
10271 : /* Split ENTRY_BB at GIMPLE_*,
10272 : so that it can be moved to the child function. */
10273 21185 : gsi = gsi_last_nondebug_bb (entry_bb);
10274 21185 : stmt = gsi_stmt (gsi);
10275 21185 : gcc_assert (stmt
10276 : && gimple_code (stmt) == gimple_code (entry_stmt));
10277 21185 : e = split_block (entry_bb, stmt);
10278 21185 : gsi_remove (&gsi, true);
10279 21185 : entry_bb = e->dest;
10280 21185 : single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10281 :
10282 : /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
10283 21185 : if (exit_bb)
10284 : {
10285 21109 : gsi = gsi_last_nondebug_bb (exit_bb);
10286 21109 : gcc_assert (!gsi_end_p (gsi)
10287 : && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
10288 21109 : stmt = gimple_build_return (NULL);
10289 21109 : gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
10290 21109 : gsi_remove (&gsi, true);
10291 : }
10292 :
10293 : /* Move the offloading region into CHILD_CFUN. */
10294 :
10295 21185 : block = gimple_block (entry_stmt);
10296 :
10297 21185 : new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
10298 21185 : if (exit_bb)
10299 21109 : single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
10300 : /* When the OMP expansion process cannot guarantee an up-to-date
10301 : loop tree arrange for the child function to fixup loops. */
10302 21185 : if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
10303 21185 : child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
10304 :
10305 : /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
10306 21185 : num = vec_safe_length (child_cfun->local_decls);
10307 650156 : for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
10308 : {
10309 628971 : t = (*child_cfun->local_decls)[srcidx];
10310 628971 : if (DECL_CONTEXT (t) == cfun->decl)
10311 137223 : continue;
10312 491748 : if (srcidx != dstidx)
10313 476774 : (*child_cfun->local_decls)[dstidx] = t;
10314 491748 : dstidx++;
10315 : }
10316 21185 : if (dstidx != num)
10317 17835 : vec_safe_truncate (child_cfun->local_decls, dstidx);
10318 :
10319 : /* Inform the callgraph about the new function. */
10320 21185 : child_cfun->curr_properties = cfun->curr_properties;
10321 21185 : child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
10322 21185 : child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
10323 21185 : cgraph_node *node = cgraph_node::get_create (child_fn);
10324 21185 : node->parallelized_function = 1;
10325 42370 : node->has_omp_variant_constructs
10326 21185 : |= cgraph_node::get (cfun->decl)->has_omp_variant_constructs;
10327 21185 : cgraph_node::add_new_function (child_fn, true);
10328 :
10329 : /* Add the new function to the offload table. */
10330 21185 : if (ENABLE_OFFLOADING)
10331 : {
10332 : if (in_lto_p)
10333 : DECL_PRESERVE_P (child_fn) = 1;
10334 : if (!is_ancestor && !is_host_only)
10335 : vec_safe_push (offload_funcs, child_fn);
10336 : }
10337 :
10338 21185 : bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
10339 21185 : && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
10340 :
10341 : /* Fix the callgraph edges for child_cfun. Those for cfun will be
10342 : fixed in a following pass. */
10343 21185 : push_cfun (child_cfun);
10344 21185 : if (need_asm)
10345 21179 : assign_assembler_name_if_needed (child_fn);
10346 21185 : cgraph_edge::rebuild_edges ();
10347 :
10348 : /* Some EH regions might become dead, see PR34608. If
10349 : pass_cleanup_cfg isn't the first pass to happen with the
10350 : new child, these dead EH edges might cause problems.
10351 : Clean them up now. */
10352 21185 : if (flag_exceptions)
10353 : {
10354 8304 : basic_block bb;
10355 8304 : bool changed = false;
10356 :
10357 119073 : FOR_EACH_BB_FN (bb, cfun)
10358 110769 : changed |= gimple_purge_dead_eh_edges (bb);
10359 8304 : if (changed)
10360 0 : cleanup_tree_cfg ();
10361 : }
10362 21185 : if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
10363 0 : verify_loop_structure ();
10364 21185 : pop_cfun ();
10365 :
10366 21185 : if (dump_file && !gimple_in_ssa_p (cfun))
10367 : {
10368 37 : omp_any_child_fn_dumped = true;
10369 37 : dump_function_header (dump_file, child_fn, dump_flags);
10370 37 : dump_function_to_file (child_fn, dump_file, dump_flags);
10371 : }
10372 :
10373 21185 : adjust_context_and_scope (region, gimple_block (entry_stmt), child_fn);
10374 :
10375 : /* Handle the case that an inner ancestor:1 target is called by an outer
10376 : target region. */
10377 21185 : if (is_ancestor)
10378 : {
10379 : cgraph_node *fn2_node;
10380 : child_fn2 = build_decl (DECL_SOURCE_LOCATION (child_fn),
10381 : FUNCTION_DECL,
10382 : clone_function_name (child_fn, "nohost"),
10383 : TREE_TYPE (child_fn));
10384 : if (in_lto_p)
10385 : DECL_PRESERVE_P (child_fn2) = 1;
10386 : TREE_STATIC (child_fn2) = 1;
10387 : DECL_ARTIFICIAL (child_fn2) = 1;
10388 : DECL_IGNORED_P (child_fn2) = 0;
10389 : TREE_PUBLIC (child_fn2) = 0;
10390 : DECL_UNINLINABLE (child_fn2) = 1;
10391 : DECL_EXTERNAL (child_fn2) = 0;
10392 : DECL_CONTEXT (child_fn2) = DECL_CONTEXT (child_fn);
10393 : DECL_INITIAL (child_fn2) = make_node (BLOCK);
10394 : BLOCK_SUPERCONTEXT (DECL_INITIAL (child_fn2)) = child_fn2;
10395 : DECL_ATTRIBUTES (child_fn)
10396 : = remove_attribute ("omp target entrypoint",
10397 : DECL_ATTRIBUTES (child_fn));
10398 : DECL_ATTRIBUTES (child_fn2)
10399 : = tree_cons (get_identifier ("omp target device_ancestor_nohost"),
10400 : NULL_TREE, copy_list (DECL_ATTRIBUTES (child_fn)));
10401 : DECL_ATTRIBUTES (child_fn)
10402 : = tree_cons (get_identifier ("omp target device_ancestor_host"),
10403 : NULL_TREE, DECL_ATTRIBUTES (child_fn));
10404 : DECL_FUNCTION_SPECIFIC_OPTIMIZATION (child_fn2)
10405 : = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (current_function_decl);
10406 : DECL_FUNCTION_SPECIFIC_TARGET (child_fn2)
10407 : = DECL_FUNCTION_SPECIFIC_TARGET (current_function_decl);
10408 : DECL_FUNCTION_VERSIONED (child_fn2)
10409 : = DECL_FUNCTION_VERSIONED (current_function_decl);
10410 :
10411 : fn2_node = cgraph_node::get_create (child_fn2);
10412 : fn2_node->offloadable = 1;
10413 : fn2_node->force_output = 1;
10414 : node->offloadable = 0;
10415 :
10416 : /* Enable pass_omp_device_lower pass. */
10417 : fn2_node = cgraph_node::get (DECL_CONTEXT (child_fn));
10418 : fn2_node->has_omp_variant_constructs = 1;
10419 :
10420 : t = build_decl (DECL_SOURCE_LOCATION (child_fn),
10421 : RESULT_DECL, NULL_TREE, void_type_node);
10422 : DECL_ARTIFICIAL (t) = 1;
10423 : DECL_IGNORED_P (t) = 1;
10424 : DECL_CONTEXT (t) = child_fn2;
10425 : DECL_RESULT (child_fn2) = t;
10426 : DECL_SAVED_TREE (child_fn2) = build1 (RETURN_EXPR,
10427 : void_type_node, NULL);
10428 : tree tmp = DECL_ARGUMENTS (child_fn);
10429 : t = build_decl (DECL_SOURCE_LOCATION (child_fn), PARM_DECL,
10430 : DECL_NAME (tmp), TREE_TYPE (tmp));
10431 : DECL_ARTIFICIAL (t) = 1;
10432 : DECL_NAMELESS (t) = 1;
10433 : DECL_ARG_TYPE (t) = ptr_type_node;
10434 : DECL_CONTEXT (t) = current_function_decl;
10435 : TREE_USED (t) = 1;
10436 : TREE_READONLY (t) = 1;
10437 : DECL_ARGUMENTS (child_fn2) = t;
10438 : gcc_assert (TREE_CHAIN (tmp) == NULL_TREE);
10439 :
10440 : gimplify_function_tree (child_fn2);
10441 : cgraph_node::add_new_function (child_fn2, true);
10442 :
10443 : vec_safe_push (offload_funcs, child_fn2);
10444 : if (dump_file && !gimple_in_ssa_p (cfun))
10445 : {
10446 : dump_function_header (dump_file, child_fn2, dump_flags);
10447 : dump_function_to_file (child_fn2, dump_file, dump_flags);
10448 : }
10449 : }
10450 : }
10451 :
10452 : /* Emit a library call to launch the offloading region, or do data
10453 : transfers. */
10454 37153 : tree t1, t2, t3, t4, depend;
10455 37153 : enum built_in_function start_ix;
10456 37153 : unsigned int flags_i = 0;
10457 :
10458 37153 : switch (gimple_omp_target_kind (entry_stmt))
10459 : {
10460 : case GF_OMP_TARGET_KIND_REGION:
10461 : start_ix = BUILT_IN_GOMP_TARGET;
10462 : break;
10463 : case GF_OMP_TARGET_KIND_DATA:
10464 : start_ix = BUILT_IN_GOMP_TARGET_DATA;
10465 : break;
10466 : case GF_OMP_TARGET_KIND_UPDATE:
10467 : start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
10468 : break;
10469 : case GF_OMP_TARGET_KIND_ENTER_DATA:
10470 : start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
10471 : break;
10472 : case GF_OMP_TARGET_KIND_EXIT_DATA:
10473 : start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
10474 : flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
10475 : break;
10476 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
10477 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
10478 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
10479 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
10480 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
10481 : start_ix = BUILT_IN_GOACC_PARALLEL;
10482 : break;
10483 : case GF_OMP_TARGET_KIND_OACC_DATA:
10484 : case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
10485 : case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
10486 : start_ix = BUILT_IN_GOACC_DATA_START;
10487 : break;
10488 : case GF_OMP_TARGET_KIND_OACC_UPDATE:
10489 : start_ix = BUILT_IN_GOACC_UPDATE;
10490 : break;
10491 : case GF_OMP_TARGET_KIND_OACC_ENTER_DATA:
10492 : start_ix = BUILT_IN_GOACC_ENTER_DATA;
10493 : break;
10494 : case GF_OMP_TARGET_KIND_OACC_EXIT_DATA:
10495 : start_ix = BUILT_IN_GOACC_EXIT_DATA;
10496 : break;
10497 : case GF_OMP_TARGET_KIND_OACC_DECLARE:
10498 : start_ix = BUILT_IN_GOACC_DECLARE;
10499 : break;
10500 0 : default:
10501 0 : gcc_unreachable ();
10502 : }
10503 :
10504 37153 : tree device = NULL_TREE;
10505 37153 : location_t device_loc = UNKNOWN_LOCATION;
10506 37153 : tree goacc_flags = NULL_TREE;
10507 37153 : bool need_device_adjustment = false;
10508 37153 : gimple_stmt_iterator adj_gsi;
10509 37153 : if (is_gimple_omp_oacc (entry_stmt))
10510 : {
10511 : /* By default, no GOACC_FLAGs are set. */
10512 14785 : goacc_flags = integer_zero_node;
10513 : }
10514 : else
10515 : {
10516 22368 : if (is_host_only)
10517 6 : device = build_int_cst (integer_type_node,
10518 : GOMP_DEVICE_HOST_FALLBACK - 1);
10519 22362 : else if ((c = omp_find_clause (clauses, OMP_CLAUSE_DEVICE)) != NULL_TREE)
10520 : {
10521 928 : device = OMP_CLAUSE_DEVICE_ID (c);
10522 : /* Ensure 'device' is of the correct type. */
10523 928 : device = fold_convert_loc (device_loc, integer_type_node, device);
10524 928 : if (TREE_CODE (device) == INTEGER_CST)
10525 : {
10526 54 : if (wi::to_wide (device) == GOMP_DEVICE_ICV)
10527 2 : device = build_int_cst (integer_type_node,
10528 : GOMP_DEVICE_HOST_FALLBACK);
10529 52 : else if (wi::to_wide (device) == GOMP_DEVICE_HOST_FALLBACK)
10530 0 : device = build_int_cst (integer_type_node,
10531 : GOMP_DEVICE_HOST_FALLBACK - 1);
10532 : }
10533 : else
10534 : need_device_adjustment = true;
10535 928 : device_loc = OMP_CLAUSE_LOCATION (c);
10536 928 : if (OMP_CLAUSE_DEVICE_ANCESTOR (c))
10537 41 : device = build_int_cst (integer_type_node,
10538 : GOMP_DEVICE_HOST_FALLBACK);
10539 : }
10540 : else
10541 : {
10542 : /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
10543 : library choose). */
10544 21434 : device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
10545 21434 : device_loc = gimple_location (entry_stmt);
10546 : }
10547 :
10548 22368 : c = omp_find_clause (clauses, OMP_CLAUSE_NOWAIT);
10549 : /* FIXME: in_reduction(...) nowait is unimplemented yet, pretend
10550 : nowait doesn't appear. */
10551 22368 : if (c && omp_find_clause (clauses, OMP_CLAUSE_IN_REDUCTION))
10552 : c = NULL;
10553 22104 : if (c)
10554 137 : flags_i |= GOMP_TARGET_FLAG_NOWAIT;
10555 : }
10556 :
10557 : /* By default, there is no conditional. */
10558 37153 : tree cond = NULL_TREE;
10559 37153 : c = omp_find_clause (clauses, OMP_CLAUSE_IF);
10560 37153 : if (c)
10561 1741 : cond = OMP_CLAUSE_IF_EXPR (c);
10562 : /* If we found the clause 'if (cond)', build:
10563 : OpenACC: goacc_flags = (cond ? goacc_flags
10564 : : goacc_flags | GOACC_FLAG_HOST_FALLBACK)
10565 : OpenMP: device = (cond ? device : GOMP_DEVICE_HOST_FALLBACK) */
10566 1741 : if (cond)
10567 : {
10568 1741 : tree *tp;
10569 1741 : if (is_gimple_omp_oacc (entry_stmt))
10570 : tp = &goacc_flags;
10571 : else
10572 666 : tp = &device;
10573 :
10574 1741 : cond = gimple_boolify (cond);
10575 :
10576 1741 : basic_block cond_bb, then_bb, else_bb;
10577 1741 : edge e;
10578 1741 : tree tmp_var = create_tmp_var (TREE_TYPE (*tp));
10579 1741 : if (offloaded)
10580 806 : e = split_block_after_labels (new_bb);
10581 : else
10582 : {
10583 935 : gsi = gsi_last_nondebug_bb (new_bb);
10584 935 : gsi_prev (&gsi);
10585 935 : e = split_block (new_bb, gsi_stmt (gsi));
10586 : }
10587 1741 : cond_bb = e->src;
10588 1741 : new_bb = e->dest;
10589 1741 : remove_edge (e);
10590 :
10591 1741 : then_bb = create_empty_bb (cond_bb);
10592 1741 : else_bb = create_empty_bb (then_bb);
10593 1741 : set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
10594 1741 : set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
10595 :
10596 1741 : stmt = gimple_build_cond_empty (cond);
10597 1741 : gsi = gsi_last_bb (cond_bb);
10598 1741 : gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
10599 :
10600 1741 : gsi = gsi_start_bb (then_bb);
10601 1741 : stmt = gimple_build_assign (tmp_var, *tp);
10602 1741 : gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
10603 1741 : adj_gsi = gsi;
10604 :
10605 1741 : gsi = gsi_start_bb (else_bb);
10606 1741 : if (is_gimple_omp_oacc (entry_stmt))
10607 1075 : stmt = gimple_build_assign (tmp_var,
10608 : BIT_IOR_EXPR,
10609 : *tp,
10610 : build_int_cst (integer_type_node,
10611 : GOACC_FLAG_HOST_FALLBACK));
10612 : else
10613 666 : stmt = gimple_build_assign (tmp_var,
10614 : build_int_cst (integer_type_node,
10615 : GOMP_DEVICE_HOST_FALLBACK));
10616 1741 : gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
10617 :
10618 1741 : make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
10619 1741 : make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
10620 1741 : add_bb_to_loop (then_bb, cond_bb->loop_father);
10621 1741 : add_bb_to_loop (else_bb, cond_bb->loop_father);
10622 1741 : make_edge (then_bb, new_bb, EDGE_FALLTHRU);
10623 1741 : make_edge (else_bb, new_bb, EDGE_FALLTHRU);
10624 :
10625 1741 : *tp = tmp_var;
10626 :
10627 1741 : gsi = gsi_last_nondebug_bb (new_bb);
10628 : }
10629 : else
10630 : {
10631 35412 : gsi = gsi_last_nondebug_bb (new_bb);
10632 :
10633 35412 : if (device != NULL_TREE)
10634 21702 : device = force_gimple_operand_gsi (&gsi, device, true, NULL_TREE,
10635 : true, GSI_SAME_STMT);
10636 35412 : if (need_device_adjustment)
10637 : {
10638 400 : tree tmp_var = create_tmp_var (TREE_TYPE (device));
10639 400 : stmt = gimple_build_assign (tmp_var, device);
10640 400 : gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10641 400 : adj_gsi = gsi_for_stmt (stmt);
10642 400 : device = tmp_var;
10643 : }
10644 : }
10645 :
10646 37153 : if ((c = omp_find_clause (clauses, OMP_CLAUSE_SELF)) != NULL_TREE)
10647 : {
10648 324 : gcc_assert ((is_gimple_omp_oacc (entry_stmt) && offloaded)
10649 : || (gimple_omp_target_kind (entry_stmt)
10650 : == GF_OMP_TARGET_KIND_OACC_DATA_KERNELS));
10651 :
10652 87 : edge e;
10653 87 : if (offloaded)
10654 237 : e = split_block_after_labels (new_bb);
10655 : else
10656 : {
10657 87 : gsi = gsi_last_nondebug_bb (new_bb);
10658 87 : gsi_prev (&gsi);
10659 87 : e = split_block (new_bb, gsi_stmt (gsi));
10660 : }
10661 324 : basic_block cond_bb = e->src;
10662 324 : new_bb = e->dest;
10663 324 : remove_edge (e);
10664 :
10665 324 : basic_block then_bb = create_empty_bb (cond_bb);
10666 324 : basic_block else_bb = create_empty_bb (then_bb);
10667 324 : set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
10668 324 : set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
10669 :
10670 324 : tree self_cond = gimple_boolify (OMP_CLAUSE_SELF_EXPR (c));
10671 324 : stmt = gimple_build_cond_empty (self_cond);
10672 324 : gsi = gsi_last_bb (cond_bb);
10673 324 : gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
10674 :
10675 324 : tree tmp_var = create_tmp_var (TREE_TYPE (goacc_flags));
10676 324 : stmt = gimple_build_assign (tmp_var, BIT_IOR_EXPR, goacc_flags,
10677 : build_int_cst (integer_type_node,
10678 : GOACC_FLAG_LOCAL_DEVICE));
10679 324 : gsi = gsi_start_bb (then_bb);
10680 324 : gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
10681 :
10682 324 : gsi = gsi_start_bb (else_bb);
10683 324 : stmt = gimple_build_assign (tmp_var, goacc_flags);
10684 324 : gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
10685 :
10686 324 : make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
10687 324 : make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
10688 324 : add_bb_to_loop (then_bb, cond_bb->loop_father);
10689 324 : add_bb_to_loop (else_bb, cond_bb->loop_father);
10690 324 : make_edge (then_bb, new_bb, EDGE_FALLTHRU);
10691 324 : make_edge (else_bb, new_bb, EDGE_FALLTHRU);
10692 :
10693 324 : goacc_flags = tmp_var;
10694 324 : gsi = gsi_last_nondebug_bb (new_bb);
10695 : }
10696 :
10697 37153 : if (need_device_adjustment)
10698 : {
10699 874 : tree uns = fold_convert (unsigned_type_node, device);
10700 874 : uns = force_gimple_operand_gsi (&adj_gsi, uns, true, NULL_TREE,
10701 : false, GSI_CONTINUE_LINKING);
10702 874 : edge e = split_block (gsi_bb (adj_gsi), gsi_stmt (adj_gsi));
10703 874 : basic_block cond_bb = e->src;
10704 874 : basic_block else_bb = e->dest;
10705 874 : if (gsi_bb (adj_gsi) == new_bb)
10706 : {
10707 400 : new_bb = else_bb;
10708 400 : gsi = gsi_last_nondebug_bb (new_bb);
10709 : }
10710 :
10711 874 : basic_block then_bb = create_empty_bb (cond_bb);
10712 874 : set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
10713 :
10714 874 : cond = build2 (GT_EXPR, boolean_type_node, uns,
10715 : build_int_cst (unsigned_type_node,
10716 : GOMP_DEVICE_HOST_FALLBACK - 1));
10717 874 : stmt = gimple_build_cond_empty (cond);
10718 874 : adj_gsi = gsi_last_bb (cond_bb);
10719 874 : gsi_insert_after (&adj_gsi, stmt, GSI_CONTINUE_LINKING);
10720 :
10721 874 : adj_gsi = gsi_start_bb (then_bb);
10722 874 : tree add = build2 (PLUS_EXPR, integer_type_node, device,
10723 : build_int_cst (integer_type_node, -1));
10724 874 : stmt = gimple_build_assign (device, add);
10725 874 : gsi_insert_after (&adj_gsi, stmt, GSI_CONTINUE_LINKING);
10726 :
10727 874 : make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
10728 874 : e->flags = EDGE_FALSE_VALUE;
10729 874 : add_bb_to_loop (then_bb, cond_bb->loop_father);
10730 874 : make_edge (then_bb, else_bb, EDGE_FALLTHRU);
10731 : }
10732 :
10733 37153 : t = gimple_omp_target_data_arg (entry_stmt);
10734 37153 : if (t == NULL)
10735 : {
10736 4891 : t1 = size_zero_node;
10737 4891 : t2 = build_zero_cst (ptr_type_node);
10738 4891 : t3 = t2;
10739 4891 : t4 = t2;
10740 : }
10741 32262 : else if (TREE_VEC_LENGTH (t) == 3 || is_gimple_omp_oacc (entry_stmt))
10742 : {
10743 32120 : t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
10744 32120 : t1 = size_binop (PLUS_EXPR, t1, size_int (1));
10745 32120 : t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
10746 32120 : t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
10747 32120 : t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
10748 : }
10749 : else
10750 : {
10751 142 : t1 = force_gimple_operand_gsi (&gsi, TREE_VEC_ELT (t, 3), true, NULL_TREE,
10752 : true, GSI_SAME_STMT);
10753 142 : t2 = force_gimple_operand_gsi (&gsi, TREE_VEC_ELT (t, 0), true, NULL_TREE,
10754 : true, GSI_SAME_STMT);
10755 142 : t3 = force_gimple_operand_gsi (&gsi, TREE_VEC_ELT (t, 1), true, NULL_TREE,
10756 : true, GSI_SAME_STMT);
10757 142 : t4 = force_gimple_operand_gsi (&gsi, TREE_VEC_ELT (t, 2), true, NULL_TREE,
10758 : true, GSI_SAME_STMT);
10759 : }
10760 :
10761 37153 : gimple *g;
10762 37153 : bool tagging = false;
10763 : /* The maximum number used by any start_ix, without varargs. */
10764 37153 : auto_vec<tree, 11> args;
10765 37153 : if (is_gimple_omp_oacc (entry_stmt))
10766 : {
10767 14785 : tree goacc_flags_m = fold_build1 (GOACC_FLAGS_MARSHAL_OP,
10768 : TREE_TYPE (goacc_flags), goacc_flags);
10769 14785 : goacc_flags_m = force_gimple_operand_gsi (&gsi, goacc_flags_m, true,
10770 : NULL_TREE, true,
10771 : GSI_SAME_STMT);
10772 14785 : args.quick_push (goacc_flags_m);
10773 : }
10774 : else
10775 22368 : args.quick_push (device);
10776 37153 : if (offloaded)
10777 21185 : args.quick_push (build_fold_addr_expr (child_fn2 ? child_fn2 : child_fn));
10778 37153 : args.quick_push (t1);
10779 37153 : args.quick_push (t2);
10780 37153 : args.quick_push (t3);
10781 37153 : args.quick_push (t4);
10782 37153 : switch (start_ix)
10783 : {
10784 : case BUILT_IN_GOACC_DATA_START:
10785 : case BUILT_IN_GOACC_DECLARE:
10786 : case BUILT_IN_GOMP_TARGET_DATA:
10787 : break;
10788 20734 : case BUILT_IN_GOMP_TARGET:
10789 20734 : case BUILT_IN_GOMP_TARGET_UPDATE:
10790 20734 : case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
10791 20734 : args.quick_push (build_int_cst (unsigned_type_node, flags_i));
10792 20734 : c = omp_find_clause (clauses, OMP_CLAUSE_DEPEND);
10793 20734 : if (c)
10794 329 : depend = OMP_CLAUSE_DECL (c);
10795 : else
10796 20405 : depend = build_int_cst (ptr_type_node, 0);
10797 20734 : args.quick_push (depend);
10798 20734 : if (start_ix == BUILT_IN_GOMP_TARGET)
10799 11790 : args.quick_push (get_target_arguments (&gsi, entry_stmt));
10800 : break;
10801 9395 : case BUILT_IN_GOACC_PARALLEL:
10802 9395 : if (lookup_attribute ("oacc serial", DECL_ATTRIBUTES (child_fn)) != NULL)
10803 : {
10804 : tree dims = NULL_TREE;
10805 : unsigned int ix;
10806 :
10807 : /* For serial constructs we set all dimensions to 1. */
10808 3024 : for (ix = GOMP_DIM_MAX; ix--;)
10809 2268 : dims = tree_cons (NULL_TREE, integer_one_node, dims);
10810 756 : oacc_replace_fn_attrib (child_fn, dims);
10811 : }
10812 : else
10813 8639 : oacc_set_fn_attrib (child_fn, clauses, &args);
10814 : tagging = true;
10815 : /* FALLTHRU */
10816 12136 : case BUILT_IN_GOACC_ENTER_DATA:
10817 12136 : case BUILT_IN_GOACC_EXIT_DATA:
10818 12136 : case BUILT_IN_GOACC_UPDATE:
10819 12136 : {
10820 12136 : tree t_async = NULL_TREE;
10821 :
10822 : /* If present, use the value specified by the respective
10823 : clause, making sure that is of the correct type. */
10824 12136 : c = omp_find_clause (clauses, OMP_CLAUSE_ASYNC);
10825 12136 : if (c)
10826 1681 : t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
10827 : integer_type_node,
10828 1681 : OMP_CLAUSE_ASYNC_EXPR (c));
10829 10455 : else if (!tagging)
10830 : /* Default values for t_async. */
10831 2431 : t_async = fold_convert_loc (gimple_location (entry_stmt),
10832 : integer_type_node,
10833 : build_int_cst (integer_type_node,
10834 : GOMP_ASYNC_SYNC));
10835 12136 : if (tagging && t_async)
10836 : {
10837 1371 : unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
10838 :
10839 1371 : if (TREE_CODE (t_async) == INTEGER_CST)
10840 : {
10841 : /* See if we can pack the async arg in to the tag's
10842 : operand. */
10843 1331 : i_async = TREE_INT_CST_LOW (t_async);
10844 1331 : if (i_async < GOMP_LAUNCH_OP_MAX)
10845 : t_async = NULL_TREE;
10846 : else
10847 825 : i_async = GOMP_LAUNCH_OP_MAX;
10848 : }
10849 1371 : args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
10850 : i_async));
10851 : }
10852 12136 : if (t_async)
10853 3566 : args.safe_push (force_gimple_operand_gsi (&gsi, t_async, true,
10854 : NULL_TREE, true,
10855 : GSI_SAME_STMT));
10856 :
10857 : /* Save the argument index, and ... */
10858 12136 : unsigned t_wait_idx = args.length ();
10859 12136 : unsigned num_waits = 0;
10860 12136 : c = omp_find_clause (clauses, OMP_CLAUSE_WAIT);
10861 12136 : if (!tagging || c)
10862 : /* ... push a placeholder. */
10863 2944 : args.safe_push (integer_zero_node);
10864 :
10865 13986 : for (; c; c = OMP_CLAUSE_CHAIN (c))
10866 1850 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
10867 : {
10868 422 : tree arg = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
10869 : integer_type_node,
10870 422 : OMP_CLAUSE_WAIT_EXPR (c));
10871 422 : arg = force_gimple_operand_gsi (&gsi, arg, true, NULL_TREE, true,
10872 : GSI_SAME_STMT);
10873 422 : args.safe_push (arg);
10874 422 : num_waits++;
10875 : }
10876 :
10877 12136 : if (!tagging || num_waits)
10878 : {
10879 203 : tree len;
10880 :
10881 : /* Now that we know the number, update the placeholder. */
10882 203 : if (tagging)
10883 203 : len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
10884 : else
10885 2741 : len = build_int_cst (integer_type_node, num_waits);
10886 2944 : len = fold_convert_loc (gimple_location (entry_stmt),
10887 : unsigned_type_node, len);
10888 2944 : args[t_wait_idx] = len;
10889 : }
10890 : }
10891 : break;
10892 : default:
10893 : gcc_unreachable ();
10894 : }
10895 23926 : if (tagging)
10896 : /* Push terminal marker - zero. */
10897 9395 : args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
10898 :
10899 37153 : if (child_fn2)
10900 : {
10901 : g = gimple_build_call_internal (IFN_GOMP_TARGET_REV, 1,
10902 : build_fold_addr_expr (child_fn));
10903 : gimple_set_location (g, gimple_location (entry_stmt));
10904 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
10905 : }
10906 :
10907 37153 : g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
10908 37153 : gimple_set_location (g, gimple_location (entry_stmt));
10909 37153 : gsi_insert_before (&gsi, g, GSI_SAME_STMT);
10910 37153 : if (!offloaded)
10911 : {
10912 15968 : g = gsi_stmt (gsi);
10913 15968 : gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
10914 15968 : gsi_remove (&gsi, true);
10915 : }
10916 37153 : }
10917 :
10918 : /* Expand the parallel region tree rooted at REGION. Expansion
10919 : proceeds in depth-first order. Innermost regions are expanded
10920 : first. This way, parallel regions that require a new function to
10921 : be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
10922 : internal dependencies in their body. */
10923 :
10924 : static void
10925 82181 : expand_omp (struct omp_region *region)
10926 : {
10927 82181 : omp_any_child_fn_dumped = false;
10928 211214 : while (region)
10929 : {
10930 129033 : location_t saved_location;
10931 129033 : gimple *inner_stmt = NULL;
10932 :
10933 : /* First, determine whether this is a combined parallel+workshare
10934 : region. */
10935 129033 : if (region->type == GIMPLE_OMP_PARALLEL)
10936 16400 : determine_parallel_type (region);
10937 :
10938 129033 : if (region->type == GIMPLE_OMP_FOR
10939 129033 : && gimple_omp_for_combined_p (last_nondebug_stmt (region->entry)))
10940 14650 : inner_stmt = last_nondebug_stmt (region->inner->entry);
10941 :
10942 129033 : if (region->inner)
10943 57478 : expand_omp (region->inner);
10944 :
10945 129033 : saved_location = input_location;
10946 129033 : if (gimple_has_location (last_nondebug_stmt (region->entry)))
10947 128849 : input_location = gimple_location (last_nondebug_stmt (region->entry));
10948 :
10949 129033 : switch (region->type)
10950 : {
10951 20296 : case GIMPLE_OMP_PARALLEL:
10952 20296 : case GIMPLE_OMP_TASK:
10953 20296 : expand_omp_taskreg (region);
10954 20296 : break;
10955 :
10956 47801 : case GIMPLE_OMP_FOR:
10957 47801 : expand_omp_for (region, inner_stmt);
10958 47801 : break;
10959 :
10960 386 : case GIMPLE_OMP_SECTIONS:
10961 386 : expand_omp_sections (region);
10962 386 : break;
10963 :
10964 : case GIMPLE_OMP_SECTION:
10965 : /* Individual omp sections are handled together with their
10966 : parent GIMPLE_OMP_SECTIONS region. */
10967 : break;
10968 :
10969 0 : case GIMPLE_OMP_STRUCTURED_BLOCK:
10970 : /* We should have gotten rid of these in gimple lowering. */
10971 0 : gcc_unreachable ();
10972 :
10973 1288 : case GIMPLE_OMP_SINGLE:
10974 1288 : case GIMPLE_OMP_SCOPE:
10975 1288 : expand_omp_single (region);
10976 1288 : break;
10977 :
10978 1120 : case GIMPLE_OMP_ORDERED:
10979 1120 : {
10980 1120 : gomp_ordered *ord_stmt
10981 1120 : = as_a <gomp_ordered *> (last_nondebug_stmt (region->entry));
10982 1120 : if (gimple_omp_ordered_standalone_p (ord_stmt))
10983 : {
10984 : /* We'll expand these when expanding corresponding
10985 : worksharing region with ordered(n) clause. */
10986 709 : gcc_assert (region->outer
10987 : && region->outer->type == GIMPLE_OMP_FOR);
10988 709 : region->ord_stmt = ord_stmt;
10989 709 : break;
10990 : }
10991 : }
10992 : /* FALLTHRU */
10993 10872 : case GIMPLE_OMP_MASTER:
10994 10872 : case GIMPLE_OMP_MASKED:
10995 10872 : case GIMPLE_OMP_TASKGROUP:
10996 10872 : case GIMPLE_OMP_CRITICAL:
10997 10872 : case GIMPLE_OMP_TEAMS:
10998 10872 : expand_omp_synch (region);
10999 10872 : break;
11000 :
11001 9665 : case GIMPLE_OMP_ATOMIC_LOAD:
11002 9665 : expand_omp_atomic (region);
11003 9665 : break;
11004 :
11005 37153 : case GIMPLE_OMP_TARGET:
11006 37153 : expand_omp_target (region);
11007 37153 : break;
11008 :
11009 0 : default:
11010 0 : gcc_unreachable ();
11011 : }
11012 :
11013 129033 : input_location = saved_location;
11014 129033 : region = region->next;
11015 : }
11016 82181 : if (omp_any_child_fn_dumped)
11017 : {
11018 109 : if (dump_file)
11019 109 : dump_function_header (dump_file, current_function_decl, dump_flags);
11020 109 : omp_any_child_fn_dumped = false;
11021 : }
11022 82181 : }
11023 :
11024 : /* Helper for build_omp_regions. Scan the dominator tree starting at
11025 : block BB. PARENT is the region that contains BB. If SINGLE_TREE is
11026 : true, the function ends once a single tree is built (otherwise, whole
11027 : forest of OMP constructs may be built). */
11028 :
11029 : static void
11030 1407729 : build_omp_regions_1 (basic_block bb, struct omp_region *parent,
11031 : bool single_tree)
11032 : {
11033 1407729 : gimple_stmt_iterator gsi;
11034 1407729 : gimple *stmt;
11035 1407729 : basic_block son;
11036 :
11037 1407729 : gsi = gsi_last_nondebug_bb (bb);
11038 1407729 : if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
11039 : {
11040 290565 : struct omp_region *region;
11041 290565 : enum gimple_code code;
11042 :
11043 290565 : stmt = gsi_stmt (gsi);
11044 290565 : code = gimple_code (stmt);
11045 290565 : if (code == GIMPLE_OMP_RETURN)
11046 : {
11047 : /* STMT is the return point out of region PARENT. Mark it
11048 : as the exit point and make PARENT the immediately
11049 : enclosing region. */
11050 101816 : gcc_assert (parent);
11051 101816 : region = parent;
11052 101816 : region->exit = bb;
11053 101816 : parent = parent->outer;
11054 : }
11055 188749 : else if (code == GIMPLE_OMP_ATOMIC_STORE)
11056 : {
11057 : /* GIMPLE_OMP_ATOMIC_STORE is analogous to
11058 : GIMPLE_OMP_RETURN, but matches with
11059 : GIMPLE_OMP_ATOMIC_LOAD. */
11060 9665 : gcc_assert (parent);
11061 9665 : gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
11062 9665 : region = parent;
11063 9665 : region->exit = bb;
11064 9665 : parent = parent->outer;
11065 : }
11066 179084 : else if (code == GIMPLE_OMP_CONTINUE)
11067 : {
11068 49665 : gcc_assert (parent);
11069 49665 : parent->cont = bb;
11070 : }
11071 129419 : else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
11072 : {
11073 : /* GIMPLE_OMP_SECTIONS_SWITCH is part of
11074 : GIMPLE_OMP_SECTIONS, and we do nothing for it. */
11075 : }
11076 : else
11077 : {
11078 129033 : region = new_omp_region (bb, code, parent);
11079 : /* Otherwise... */
11080 129033 : if (code == GIMPLE_OMP_TARGET)
11081 : {
11082 37153 : switch (gimple_omp_target_kind (stmt))
11083 : {
11084 : case GF_OMP_TARGET_KIND_REGION:
11085 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11086 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
11087 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
11088 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
11089 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
11090 : break;
11091 : case GF_OMP_TARGET_KIND_UPDATE:
11092 : case GF_OMP_TARGET_KIND_ENTER_DATA:
11093 : case GF_OMP_TARGET_KIND_EXIT_DATA:
11094 : case GF_OMP_TARGET_KIND_DATA:
11095 : case GF_OMP_TARGET_KIND_OACC_DATA:
11096 : case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
11097 : case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
11098 : case GF_OMP_TARGET_KIND_OACC_UPDATE:
11099 : case GF_OMP_TARGET_KIND_OACC_ENTER_DATA:
11100 : case GF_OMP_TARGET_KIND_OACC_EXIT_DATA:
11101 : case GF_OMP_TARGET_KIND_OACC_DECLARE:
11102 : /* ..., other than for those stand-alone directives...
11103 : To be precise, target data isn't stand-alone, but
11104 : gimplifier put the end API call into try finally block
11105 : for it, so omp expansion can treat it as such. */
11106 : region = NULL;
11107 : break;
11108 0 : default:
11109 0 : gcc_unreachable ();
11110 : }
11111 : }
11112 91880 : else if (code == GIMPLE_OMP_ORDERED
11113 91880 : && gimple_omp_ordered_standalone_p (stmt))
11114 : /* #pragma omp ordered depend is also just a stand-alone
11115 : directive. */
11116 : region = NULL;
11117 91171 : else if (code == GIMPLE_OMP_TASK
11118 91171 : && gimple_omp_task_taskwait_p (stmt))
11119 : /* #pragma omp taskwait depend(...) is a stand-alone directive. */
11120 : region = NULL;
11121 91087 : else if (code == GIMPLE_OMP_TASKGROUP)
11122 : /* #pragma omp taskgroup isn't a stand-alone directive, but
11123 : gimplifier put the end API call into try finally block
11124 : for it, so omp expansion can treat it as such. */
11125 : region = NULL;
11126 : /* ..., this directive becomes the parent for a new region. */
11127 : if (region)
11128 : parent = region;
11129 : }
11130 : }
11131 :
11132 1407729 : if (single_tree && !parent)
11133 0 : return;
11134 :
11135 1407729 : for (son = first_dom_son (CDI_DOMINATORS, bb);
11136 2738407 : son;
11137 1330678 : son = next_dom_son (CDI_DOMINATORS, son))
11138 1330678 : build_omp_regions_1 (son, parent, single_tree);
11139 : }
11140 :
11141 : /* Builds the tree of OMP regions rooted at ROOT, storing it to
11142 : root_omp_region. */
11143 :
11144 : static void
11145 0 : build_omp_regions_root (basic_block root)
11146 : {
11147 0 : gcc_assert (root_omp_region == NULL);
11148 0 : build_omp_regions_1 (root, NULL, true);
11149 0 : gcc_assert (root_omp_region != NULL);
11150 0 : }
11151 :
11152 : /* Expands omp construct (and its subconstructs) starting in HEAD. */
11153 :
11154 : void
11155 0 : omp_expand_local (basic_block head)
11156 : {
11157 0 : build_omp_regions_root (head);
11158 0 : if (dump_file && (dump_flags & TDF_DETAILS))
11159 : {
11160 0 : fprintf (dump_file, "\nOMP region tree\n\n");
11161 0 : dump_omp_region (dump_file, root_omp_region, 0);
11162 0 : fprintf (dump_file, "\n");
11163 : }
11164 :
11165 0 : remove_exit_barriers (root_omp_region);
11166 0 : expand_omp (root_omp_region);
11167 :
11168 0 : omp_free_regions ();
11169 0 : }
11170 :
11171 : /* Scan the CFG and build a tree of OMP regions. Return the root of
11172 : the OMP region tree. */
11173 :
11174 : static void
11175 77051 : build_omp_regions (void)
11176 : {
11177 77051 : gcc_assert (root_omp_region == NULL);
11178 77051 : calculate_dominance_info (CDI_DOMINATORS);
11179 77051 : build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
11180 77051 : }
11181 :
11182 : /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
11183 :
11184 : static unsigned int
11185 77051 : execute_expand_omp (void)
11186 : {
11187 77051 : build_omp_regions ();
11188 :
11189 77051 : if (!root_omp_region)
11190 : return 0;
11191 :
11192 24703 : if (dump_file)
11193 : {
11194 284 : fprintf (dump_file, "\nOMP region tree\n\n");
11195 284 : dump_omp_region (dump_file, root_omp_region, 0);
11196 284 : fprintf (dump_file, "\n");
11197 : }
11198 :
11199 24703 : remove_exit_barriers (root_omp_region);
11200 :
11201 24703 : expand_omp (root_omp_region);
11202 :
11203 24703 : omp_free_regions ();
11204 :
11205 24703 : return (TODO_cleanup_cfg
11206 48857 : | (gimple_in_ssa_p (cfun) ? TODO_update_ssa_only_virtuals : 0));
11207 : }
11208 :
11209 : /* OMP expansion -- the default pass, run before creation of SSA form. */
11210 :
11211 : namespace {
11212 :
11213 : const pass_data pass_data_expand_omp =
11214 : {
11215 : GIMPLE_PASS, /* type */
11216 : "ompexp", /* name */
11217 : OPTGROUP_OMP, /* optinfo_flags */
11218 : TV_NONE, /* tv_id */
11219 : PROP_gimple_any, /* properties_required */
11220 : PROP_gimple_eomp, /* properties_provided */
11221 : 0, /* properties_destroyed */
11222 : 0, /* todo_flags_start */
11223 : 0, /* todo_flags_finish */
11224 : };
11225 :
11226 : class pass_expand_omp : public gimple_opt_pass
11227 : {
11228 : public:
11229 294196 : pass_expand_omp (gcc::context *ctxt)
11230 588392 : : gimple_opt_pass (pass_data_expand_omp, ctxt)
11231 : {}
11232 :
11233 : /* opt_pass methods: */
11234 3027071 : unsigned int execute (function *) final override
11235 : {
11236 3019799 : bool gate = ((flag_openacc != 0 || flag_openmp != 0
11237 2972197 : || flag_openmp_simd != 0)
11238 3076931 : && !seen_error ());
11239 :
11240 : /* This pass always runs, to provide PROP_gimple_eomp.
11241 : But often, there is nothing to do. */
11242 53034 : if (!gate)
11243 : return 0;
11244 :
11245 53034 : return execute_expand_omp ();
11246 : }
11247 :
11248 : }; // class pass_expand_omp
11249 :
11250 : } // anon namespace
11251 :
11252 : gimple_opt_pass *
11253 294196 : make_pass_expand_omp (gcc::context *ctxt)
11254 : {
11255 294196 : return new pass_expand_omp (ctxt);
11256 : }
11257 :
11258 : namespace {
11259 :
11260 : const pass_data pass_data_expand_omp_ssa =
11261 : {
11262 : GIMPLE_PASS, /* type */
11263 : "ompexpssa", /* name */
11264 : OPTGROUP_OMP, /* optinfo_flags */
11265 : TV_NONE, /* tv_id */
11266 : PROP_cfg | PROP_ssa, /* properties_required */
11267 : PROP_gimple_eomp, /* properties_provided */
11268 : 0, /* properties_destroyed */
11269 : 0, /* todo_flags_start */
11270 : TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
11271 : };
11272 :
11273 : class pass_expand_omp_ssa : public gimple_opt_pass
11274 : {
11275 : public:
11276 588392 : pass_expand_omp_ssa (gcc::context *ctxt)
11277 1176784 : : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
11278 : {}
11279 :
11280 : /* opt_pass methods: */
11281 246135 : bool gate (function *fun) final override
11282 : {
11283 246135 : return !(fun->curr_properties & PROP_gimple_eomp);
11284 : }
11285 24017 : unsigned int execute (function *) final override
11286 : {
11287 24017 : return execute_expand_omp ();
11288 : }
11289 294196 : opt_pass * clone () final override
11290 : {
11291 294196 : return new pass_expand_omp_ssa (m_ctxt);
11292 : }
11293 :
11294 : }; // class pass_expand_omp_ssa
11295 :
11296 : } // anon namespace
11297 :
11298 : gimple_opt_pass *
11299 294196 : make_pass_expand_omp_ssa (gcc::context *ctxt)
11300 : {
11301 294196 : return new pass_expand_omp_ssa (ctxt);
11302 : }
11303 :
11304 : /* Called from tree-cfg.cc::make_edges to create cfg edges for all relevant
11305 : GIMPLE_* codes. */
11306 :
11307 : bool
11308 291622 : omp_make_gimple_edges (basic_block bb, struct omp_region **region,
11309 : int *region_idx)
11310 : {
11311 291622 : gimple *last = last_nondebug_stmt (bb);
11312 291622 : enum gimple_code code = gimple_code (last);
11313 291622 : struct omp_region *cur_region = *region;
11314 291622 : bool fallthru = false;
11315 :
11316 291622 : switch (code)
11317 : {
11318 75563 : case GIMPLE_OMP_PARALLEL:
11319 75563 : case GIMPLE_OMP_FOR:
11320 75563 : case GIMPLE_OMP_SINGLE:
11321 75563 : case GIMPLE_OMP_TEAMS:
11322 75563 : case GIMPLE_OMP_MASTER:
11323 75563 : case GIMPLE_OMP_MASKED:
11324 75563 : case GIMPLE_OMP_SCOPE:
11325 75563 : case GIMPLE_OMP_CRITICAL:
11326 75563 : case GIMPLE_OMP_SECTION:
11327 75563 : cur_region = new_omp_region (bb, code, cur_region);
11328 75563 : fallthru = true;
11329 75563 : break;
11330 :
11331 536 : case GIMPLE_OMP_TASKGROUP:
11332 536 : cur_region = new_omp_region (bb, code, cur_region);
11333 536 : fallthru = true;
11334 536 : cur_region = cur_region->outer;
11335 536 : break;
11336 :
11337 3896 : case GIMPLE_OMP_TASK:
11338 3896 : cur_region = new_omp_region (bb, code, cur_region);
11339 3896 : fallthru = true;
11340 3896 : if (gimple_omp_task_taskwait_p (last))
11341 84 : cur_region = cur_region->outer;
11342 : break;
11343 :
11344 1124 : case GIMPLE_OMP_ORDERED:
11345 1124 : cur_region = new_omp_region (bb, code, cur_region);
11346 1124 : fallthru = true;
11347 1124 : if (gimple_omp_ordered_standalone_p (last))
11348 713 : cur_region = cur_region->outer;
11349 : break;
11350 :
11351 37183 : case GIMPLE_OMP_TARGET:
11352 37183 : cur_region = new_omp_region (bb, code, cur_region);
11353 37183 : fallthru = true;
11354 37183 : switch (gimple_omp_target_kind (last))
11355 : {
11356 : case GF_OMP_TARGET_KIND_REGION:
11357 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11358 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
11359 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
11360 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
11361 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
11362 : break;
11363 15970 : case GF_OMP_TARGET_KIND_UPDATE:
11364 15970 : case GF_OMP_TARGET_KIND_ENTER_DATA:
11365 15970 : case GF_OMP_TARGET_KIND_EXIT_DATA:
11366 15970 : case GF_OMP_TARGET_KIND_DATA:
11367 15970 : case GF_OMP_TARGET_KIND_OACC_DATA:
11368 15970 : case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
11369 15970 : case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
11370 15970 : case GF_OMP_TARGET_KIND_OACC_UPDATE:
11371 15970 : case GF_OMP_TARGET_KIND_OACC_ENTER_DATA:
11372 15970 : case GF_OMP_TARGET_KIND_OACC_EXIT_DATA:
11373 15970 : case GF_OMP_TARGET_KIND_OACC_DECLARE:
11374 15970 : cur_region = cur_region->outer;
11375 15970 : break;
11376 0 : default:
11377 0 : gcc_unreachable ();
11378 : }
11379 : break;
11380 :
11381 386 : case GIMPLE_OMP_SECTIONS:
11382 386 : cur_region = new_omp_region (bb, code, cur_region);
11383 386 : fallthru = true;
11384 386 : break;
11385 :
11386 : case GIMPLE_OMP_SECTIONS_SWITCH:
11387 : fallthru = false;
11388 : break;
11389 :
11390 19714 : case GIMPLE_OMP_ATOMIC_LOAD:
11391 19714 : case GIMPLE_OMP_ATOMIC_STORE:
11392 19714 : fallthru = true;
11393 19714 : break;
11394 :
11395 101385 : case GIMPLE_OMP_RETURN:
11396 : /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11397 : somewhere other than the next block. This will be
11398 : created later. */
11399 101385 : cur_region->exit = bb;
11400 101385 : if (cur_region->type == GIMPLE_OMP_TASK)
11401 : /* Add an edge corresponding to not scheduling the task
11402 : immediately. */
11403 3812 : make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
11404 101385 : fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11405 101385 : cur_region = cur_region->outer;
11406 101385 : break;
11407 :
11408 51449 : case GIMPLE_OMP_CONTINUE:
11409 51449 : cur_region->cont = bb;
11410 51449 : switch (cur_region->type)
11411 : {
11412 47251 : case GIMPLE_OMP_FOR:
11413 : /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11414 : succs edges as abnormal to prevent splitting
11415 : them. */
11416 47251 : single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11417 : /* Make the loopback edge. */
11418 47251 : make_edge (bb, single_succ (cur_region->entry),
11419 : EDGE_ABNORMAL);
11420 :
11421 : /* Create an edge from GIMPLE_OMP_FOR to exit, which
11422 : corresponds to the case that the body of the loop
11423 : is not executed at all. */
11424 47251 : make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11425 47251 : make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11426 47251 : fallthru = false;
11427 47251 : break;
11428 :
11429 386 : case GIMPLE_OMP_SECTIONS:
11430 : /* Wire up the edges into and out of the nested sections. */
11431 386 : {
11432 386 : basic_block switch_bb = single_succ (cur_region->entry);
11433 :
11434 386 : struct omp_region *i;
11435 1249 : for (i = cur_region->inner; i ; i = i->next)
11436 : {
11437 863 : gcc_assert (i->type == GIMPLE_OMP_SECTION);
11438 863 : make_edge (switch_bb, i->entry, 0);
11439 863 : make_edge (i->exit, bb, EDGE_FALLTHRU);
11440 : }
11441 :
11442 : /* Make the loopback edge to the block with
11443 : GIMPLE_OMP_SECTIONS_SWITCH. */
11444 386 : make_edge (bb, switch_bb, 0);
11445 :
11446 : /* Make the edge from the switch to exit. */
11447 386 : make_edge (switch_bb, bb->next_bb, 0);
11448 386 : fallthru = false;
11449 : }
11450 386 : break;
11451 :
11452 : case GIMPLE_OMP_TASK:
11453 : fallthru = true;
11454 : break;
11455 :
11456 0 : default:
11457 0 : gcc_unreachable ();
11458 : }
11459 : break;
11460 :
11461 0 : default:
11462 0 : gcc_unreachable ();
11463 : }
11464 :
11465 291622 : if (*region != cur_region)
11466 : {
11467 202770 : *region = cur_region;
11468 202770 : if (cur_region)
11469 161318 : *region_idx = cur_region->entry->index;
11470 : else
11471 41452 : *region_idx = 0;
11472 : }
11473 :
11474 291622 : return fallthru;
11475 : }
|