Branch data Line data Source code
1 : : /* General types and functions that are useful for processing of OpenMP,
2 : : OpenACC and similar directives at various stages of compilation.
3 : :
4 : : Copyright (C) 2005-2024 Free Software Foundation, Inc.
5 : :
6 : : This file is part of GCC.
7 : :
8 : : GCC is free software; you can redistribute it and/or modify it under
9 : : the terms of the GNU General Public License as published by the Free
10 : : Software Foundation; either version 3, or (at your option) any later
11 : : version.
12 : :
13 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : : for more details.
17 : :
18 : : You should have received a copy of the GNU General Public License
19 : : along with GCC; see the file COPYING3. If not see
20 : : <http://www.gnu.org/licenses/>. */
21 : :
22 : : #include "config.h"
23 : : #include "system.h"
24 : : #include "coretypes.h"
25 : : #include "backend.h"
26 : : #include "target.h"
27 : : #include "tree.h"
28 : : #include "gimple.h"
29 : : #include "ssa.h"
30 : : #include "diagnostic-core.h"
31 : : #include "fold-const.h"
32 : : #include "langhooks.h"
33 : : #include "omp-general.h"
34 : : #include "stringpool.h"
35 : : #include "attribs.h"
36 : : #include "gimplify.h"
37 : : #include "cgraph.h"
38 : : #include "alloc-pool.h"
39 : : #include "symbol-summary.h"
40 : : #include "tree-pass.h"
41 : : #include "omp-device-properties.h"
42 : : #include "tree-iterator.h"
43 : : #include "data-streamer.h"
44 : : #include "streamer-hooks.h"
45 : : #include "opts.h"
46 : : #include "tree-pretty-print.h"
47 : :
48 : : enum omp_requires omp_requires_mask;
49 : :
50 : : /* Find an OMP clause of type KIND within CLAUSES. */
51 : : tree
52 : 1168930 : omp_find_clause (tree clauses, enum omp_clause_code kind)
53 : : {
54 : 4322039 : for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55 : 3403262 : if (OMP_CLAUSE_CODE (clauses) == kind)
56 : 250153 : return clauses;
57 : :
58 : : return NULL_TREE;
59 : : }
60 : :
61 : : /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
62 : : allocatable or pointer attribute. */
63 : : bool
64 : 15326 : omp_is_allocatable_or_ptr (tree decl)
65 : : {
66 : 15326 : return lang_hooks.decls.omp_is_allocatable_or_ptr (decl);
67 : : }
68 : :
69 : : /* Check whether this DECL belongs to a Fortran optional argument.
70 : : With 'for_present_check' set to false, decls which are optional parameters
71 : : themselve are returned as tree - or a NULL_TREE otherwise. Those decls are
72 : : always pointers. With 'for_present_check' set to true, the decl for checking
73 : : whether an argument is present is returned; for arguments with value
74 : : attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is
75 : : unrelated to optional arguments, NULL_TREE is returned. */
76 : :
77 : : tree
78 : 12844 : omp_check_optional_argument (tree decl, bool for_present_check)
79 : : {
80 : 12844 : return lang_hooks.decls.omp_check_optional_argument (decl, for_present_check);
81 : : }
82 : :
83 : : /* Return true if TYPE is an OpenMP mappable type. */
84 : :
85 : : bool
86 : 44505 : omp_mappable_type (tree type)
87 : : {
88 : : /* Mappable type has to be complete. */
89 : 44505 : if (type == error_mark_node || !COMPLETE_TYPE_P (type))
90 : 188 : return false;
91 : : return true;
92 : : }
93 : :
94 : : /* True if OpenMP should privatize what this DECL points to rather
95 : : than the DECL itself. */
96 : :
97 : : bool
98 : 4874892 : omp_privatize_by_reference (tree decl)
99 : : {
100 : 4874892 : return lang_hooks.decls.omp_privatize_by_reference (decl);
101 : : }
102 : :
103 : : /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or GT_EXPR,
104 : : given that V is the loop index variable and STEP is loop step. */
105 : :
106 : : void
107 : 191940 : omp_adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2,
108 : : tree v, tree step)
109 : : {
110 : 191940 : switch (*cond_code)
111 : : {
112 : : case LT_EXPR:
113 : : case GT_EXPR:
114 : : break;
115 : :
116 : 29865 : case NE_EXPR:
117 : 29865 : gcc_assert (TREE_CODE (step) == INTEGER_CST);
118 : 29865 : if (TREE_CODE (TREE_TYPE (v)) == INTEGER_TYPE
119 : 29865 : || TREE_CODE (TREE_TYPE (v)) == BITINT_TYPE)
120 : : {
121 : 25021 : if (integer_onep (step))
122 : 17737 : *cond_code = LT_EXPR;
123 : : else
124 : : {
125 : 7284 : gcc_assert (integer_minus_onep (step));
126 : 7284 : *cond_code = GT_EXPR;
127 : : }
128 : : }
129 : : else
130 : : {
131 : 4844 : tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v)));
132 : 4844 : gcc_assert (TREE_CODE (unit) == INTEGER_CST);
133 : 4844 : if (tree_int_cst_equal (unit, step))
134 : 3358 : *cond_code = LT_EXPR;
135 : : else
136 : : {
137 : 1486 : gcc_assert (wi::neg (wi::to_widest (unit))
138 : : == wi::to_widest (step));
139 : 1486 : *cond_code = GT_EXPR;
140 : : }
141 : : }
142 : :
143 : : break;
144 : :
145 : 27238 : case LE_EXPR:
146 : 27238 : if (POINTER_TYPE_P (TREE_TYPE (*n2)))
147 : : {
148 : 123 : tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v)));
149 : 123 : gcc_assert (TREE_CODE (unit) == INTEGER_CST);
150 : 123 : *n2 = fold_build_pointer_plus_loc (loc, *n2, unit);
151 : : }
152 : : else
153 : 27115 : *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
154 : 27115 : build_int_cst (TREE_TYPE (*n2), 1));
155 : 27238 : *cond_code = LT_EXPR;
156 : 27238 : break;
157 : 1808 : case GE_EXPR:
158 : 1808 : if (POINTER_TYPE_P (TREE_TYPE (*n2)))
159 : : {
160 : 137 : tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v)));
161 : 137 : gcc_assert (TREE_CODE (unit) == INTEGER_CST);
162 : 137 : unit = convert_to_ptrofftype_loc (loc, unit);
163 : 137 : unit = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (unit),
164 : : unit);
165 : 137 : *n2 = fold_build_pointer_plus_loc (loc, *n2, unit);
166 : : }
167 : : else
168 : 1671 : *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
169 : 1671 : build_int_cst (TREE_TYPE (*n2), 1));
170 : 1808 : *cond_code = GT_EXPR;
171 : 1808 : break;
172 : 0 : default:
173 : 0 : gcc_unreachable ();
174 : : }
175 : 191940 : }
176 : :
177 : : /* Return the looping step from INCR, extracted from the step of a gimple omp
178 : : for statement. */
179 : :
180 : : tree
181 : 190776 : omp_get_for_step_from_incr (location_t loc, tree incr)
182 : : {
183 : 190776 : tree step;
184 : 190776 : switch (TREE_CODE (incr))
185 : : {
186 : 168545 : case PLUS_EXPR:
187 : 168545 : step = TREE_OPERAND (incr, 1);
188 : 168545 : break;
189 : 16136 : case POINTER_PLUS_EXPR:
190 : 16136 : step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
191 : 16136 : break;
192 : 6095 : case MINUS_EXPR:
193 : 6095 : step = TREE_OPERAND (incr, 1);
194 : 6095 : step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
195 : 6095 : break;
196 : 0 : default:
197 : 0 : gcc_unreachable ();
198 : : }
199 : 190776 : return step;
200 : : }
201 : :
202 : : /* Extract the header elements of parallel loop FOR_STMT and store
203 : : them into *FD. */
204 : :
205 : : void
206 : 124973 : omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
207 : : struct omp_for_data_loop *loops)
208 : : {
209 : 124973 : tree t, var, *collapse_iter, *collapse_count;
210 : 124973 : tree count = NULL_TREE, iter_type = long_integer_type_node;
211 : 124973 : struct omp_for_data_loop *loop;
212 : 124973 : int i;
213 : 124973 : struct omp_for_data_loop dummy_loop;
214 : 124973 : location_t loc = gimple_location (for_stmt);
215 : 124973 : bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
216 : 124973 : bool distribute = gimple_omp_for_kind (for_stmt)
217 : 124973 : == GF_OMP_FOR_KIND_DISTRIBUTE;
218 : 124973 : bool taskloop = gimple_omp_for_kind (for_stmt)
219 : 124973 : == GF_OMP_FOR_KIND_TASKLOOP;
220 : 124973 : bool order_reproducible = false;
221 : 124973 : tree iterv, countv;
222 : :
223 : 124973 : fd->for_stmt = for_stmt;
224 : 124973 : fd->pre = NULL;
225 : 124973 : fd->have_nowait = distribute || simd;
226 : 124973 : fd->have_ordered = false;
227 : 124973 : fd->have_reductemp = false;
228 : 124973 : fd->have_pointer_condtemp = false;
229 : 124973 : fd->have_scantemp = false;
230 : 124973 : fd->have_nonctrl_scantemp = false;
231 : 124973 : fd->non_rect = false;
232 : 124973 : fd->lastprivate_conditional = 0;
233 : 124973 : fd->tiling = NULL_TREE;
234 : 124973 : fd->collapse = 1;
235 : 124973 : fd->ordered = 0;
236 : 124973 : fd->first_nonrect = -1;
237 : 124973 : fd->last_nonrect = -1;
238 : 124973 : fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
239 : 124973 : fd->sched_modifiers = 0;
240 : 124973 : fd->chunk_size = NULL_TREE;
241 : 124973 : fd->simd_schedule = false;
242 : 124973 : fd->first_inner_iterations = NULL_TREE;
243 : 124973 : fd->factor = NULL_TREE;
244 : 124973 : fd->adjn1 = NULL_TREE;
245 : 124973 : collapse_iter = NULL;
246 : 124973 : collapse_count = NULL;
247 : :
248 : 634672 : for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
249 : 509699 : switch (OMP_CLAUSE_CODE (t))
250 : : {
251 : 44392 : case OMP_CLAUSE_NOWAIT:
252 : 44392 : fd->have_nowait = true;
253 : 44392 : break;
254 : 1389 : case OMP_CLAUSE_ORDERED:
255 : 1389 : fd->have_ordered = true;
256 : 1389 : if (OMP_CLAUSE_ORDERED_DOACROSS (t))
257 : : {
258 : 692 : if (OMP_CLAUSE_ORDERED_EXPR (t))
259 : 672 : fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
260 : : else
261 : 20 : fd->ordered = -1;
262 : : }
263 : : break;
264 : 30353 : case OMP_CLAUSE_SCHEDULE:
265 : 30353 : gcc_assert (!distribute && !taskloop);
266 : 30353 : fd->sched_kind
267 : 30353 : = (enum omp_clause_schedule_kind)
268 : 30353 : (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
269 : 30353 : fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
270 : 30353 : & ~OMP_CLAUSE_SCHEDULE_MASK);
271 : 30353 : fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
272 : 30353 : fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
273 : 30353 : break;
274 : 7004 : case OMP_CLAUSE_DIST_SCHEDULE:
275 : 7004 : gcc_assert (distribute);
276 : 7004 : fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
277 : 7004 : break;
278 : 41249 : case OMP_CLAUSE_COLLAPSE:
279 : 41249 : fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
280 : 41249 : if (fd->collapse > 1)
281 : : {
282 : 33684 : collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
283 : 33684 : collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
284 : : }
285 : : break;
286 : 338 : case OMP_CLAUSE_TILE:
287 : 338 : fd->tiling = OMP_CLAUSE_TILE_LIST (t);
288 : 338 : fd->collapse = list_length (fd->tiling);
289 : 338 : gcc_assert (fd->collapse);
290 : 338 : collapse_iter = &OMP_CLAUSE_TILE_ITERVAR (t);
291 : 338 : collapse_count = &OMP_CLAUSE_TILE_COUNT (t);
292 : 338 : break;
293 : 482 : case OMP_CLAUSE__REDUCTEMP_:
294 : 482 : fd->have_reductemp = true;
295 : 482 : break;
296 : 40518 : case OMP_CLAUSE_LASTPRIVATE:
297 : 40518 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t))
298 : 1504 : fd->lastprivate_conditional++;
299 : : break;
300 : 1556 : case OMP_CLAUSE__CONDTEMP_:
301 : 1556 : if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t))))
302 : 185 : fd->have_pointer_condtemp = true;
303 : : break;
304 : 1102 : case OMP_CLAUSE__SCANTEMP_:
305 : 1102 : fd->have_scantemp = true;
306 : 1102 : if (!OMP_CLAUSE__SCANTEMP__ALLOC (t)
307 : 1102 : && !OMP_CLAUSE__SCANTEMP__CONTROL (t))
308 : 205 : fd->have_nonctrl_scantemp = true;
309 : : break;
310 : 7544 : case OMP_CLAUSE_ORDER:
311 : : /* FIXME: For OpenMP 5.2 this should change to
312 : : if (OMP_CLAUSE_ORDER_REPRODUCIBLE (t))
313 : : (with the exception of loop construct but that lowers to
314 : : no schedule/dist_schedule clauses currently). */
315 : 7544 : if (!OMP_CLAUSE_ORDER_UNCONSTRAINED (t))
316 : 509699 : order_reproducible = true;
317 : : default:
318 : : break;
319 : : }
320 : :
321 : 124973 : if (fd->ordered == -1)
322 : 20 : fd->ordered = fd->collapse;
323 : :
324 : : /* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime})
325 : : we have either the option to expensively remember at runtime how we've
326 : : distributed work from first loop and reuse that in following loops with
327 : : the same number of iterations and schedule, or just force static schedule.
328 : : OpenMP API calls etc. aren't allowed in order(concurrent) bodies so
329 : : users can't observe it easily anyway. */
330 : 124973 : if (order_reproducible)
331 : 7249 : fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
332 : 124973 : if (fd->collapse > 1 || fd->tiling)
333 : 34018 : fd->loops = loops;
334 : : else
335 : 90955 : fd->loops = &fd->loop;
336 : :
337 : 124973 : if (fd->ordered && fd->collapse == 1 && loops != NULL)
338 : : {
339 : 184 : fd->loops = loops;
340 : 184 : iterv = NULL_TREE;
341 : 184 : countv = NULL_TREE;
342 : 184 : collapse_iter = &iterv;
343 : 184 : collapse_count = &countv;
344 : : }
345 : :
346 : : /* FIXME: for now map schedule(auto) to schedule(static).
347 : : There should be analysis to determine whether all iterations
348 : : are approximately the same amount of work (then schedule(static)
349 : : is best) or if it varies (then schedule(dynamic,N) is better). */
350 : 124973 : if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
351 : : {
352 : 5747 : fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
353 : 5747 : gcc_assert (fd->chunk_size == NULL);
354 : : }
355 : 124973 : gcc_assert ((fd->collapse == 1 && !fd->tiling) || collapse_iter != NULL);
356 : 124973 : if (taskloop)
357 : 9604 : fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
358 : 124973 : if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
359 : 16605 : gcc_assert (fd->chunk_size == NULL);
360 : 108368 : else if (fd->chunk_size == NULL)
361 : : {
362 : : /* We only need to compute a default chunk size for ordered
363 : : static loops and dynamic loops. */
364 : 85313 : if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
365 : 84754 : || fd->have_ordered)
366 : 1270 : fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
367 : 1270 : ? integer_zero_node : integer_one_node;
368 : : }
369 : :
370 : 124973 : int cnt = fd->ordered ? fd->ordered : fd->collapse;
371 : 124973 : int single_nonrect = -1;
372 : 124973 : tree single_nonrect_count = NULL_TREE;
373 : 124973 : enum tree_code single_nonrect_cond_code = ERROR_MARK;
374 : 188918 : for (i = 1; i < cnt; i++)
375 : : {
376 : 64073 : tree n1 = gimple_omp_for_initial (for_stmt, i);
377 : 64073 : tree n2 = gimple_omp_for_final (for_stmt, i);
378 : 64073 : if (TREE_CODE (n1) == TREE_VEC)
379 : : {
380 : 1786 : if (fd->non_rect)
381 : : {
382 : : single_nonrect = -1;
383 : : break;
384 : : }
385 : 2152 : for (int j = i - 1; j >= 0; j--)
386 : 2152 : if (TREE_VEC_ELT (n1, 0) == gimple_omp_for_index (for_stmt, j))
387 : : {
388 : : single_nonrect = j;
389 : : break;
390 : : }
391 : 1664 : fd->non_rect = true;
392 : : }
393 : 62287 : else if (TREE_CODE (n2) == TREE_VEC)
394 : : {
395 : 531 : if (fd->non_rect)
396 : : {
397 : : single_nonrect = -1;
398 : : break;
399 : : }
400 : 681 : for (int j = i - 1; j >= 0; j--)
401 : 681 : if (TREE_VEC_ELT (n2, 0) == gimple_omp_for_index (for_stmt, j))
402 : : {
403 : : single_nonrect = j;
404 : : break;
405 : : }
406 : 525 : fd->non_rect = true;
407 : : }
408 : : }
409 : 314103 : for (i = 0; i < cnt; i++)
410 : : {
411 : 189130 : if (i == 0
412 : 124973 : && fd->collapse == 1
413 : 91127 : && !fd->tiling
414 : 90955 : && (fd->ordered == 0 || loops == NULL))
415 : 90771 : loop = &fd->loop;
416 : 98175 : else if (loops != NULL)
417 : 32574 : loop = loops + i;
418 : : else
419 : : loop = &dummy_loop;
420 : :
421 : 189130 : loop->v = gimple_omp_for_index (for_stmt, i);
422 : 189130 : gcc_assert (SSA_VAR_P (loop->v));
423 : 189130 : gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
424 : : || TREE_CODE (TREE_TYPE (loop->v)) == BITINT_TYPE
425 : : || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
426 : 189130 : var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
427 : 189130 : loop->n1 = gimple_omp_for_initial (for_stmt, i);
428 : 189130 : loop->m1 = NULL_TREE;
429 : 189130 : loop->m2 = NULL_TREE;
430 : 189130 : loop->outer = 0;
431 : 189130 : loop->non_rect_referenced = false;
432 : 189130 : if (TREE_CODE (loop->n1) == TREE_VEC)
433 : : {
434 : 2313 : for (int j = i - 1; j >= 0; j--)
435 : 2313 : if (TREE_VEC_ELT (loop->n1, 0) == gimple_omp_for_index (for_stmt, j))
436 : : {
437 : 1786 : loop->outer = i - j;
438 : 1786 : if (loops != NULL)
439 : 639 : loops[j].non_rect_referenced = true;
440 : 1786 : if (fd->first_nonrect == -1 || fd->first_nonrect > j)
441 : 1664 : fd->first_nonrect = j;
442 : : break;
443 : : }
444 : 1786 : gcc_assert (loop->outer);
445 : 1786 : loop->m1 = TREE_VEC_ELT (loop->n1, 1);
446 : 1786 : loop->n1 = TREE_VEC_ELT (loop->n1, 2);
447 : 1786 : fd->non_rect = true;
448 : 1786 : fd->last_nonrect = i;
449 : : }
450 : :
451 : 189130 : loop->cond_code = gimple_omp_for_cond (for_stmt, i);
452 : 189130 : loop->n2 = gimple_omp_for_final (for_stmt, i);
453 : 189130 : gcc_assert (loop->cond_code != NE_EXPR
454 : : || (gimple_omp_for_kind (for_stmt)
455 : : != GF_OMP_FOR_KIND_OACC_LOOP));
456 : 189130 : if (TREE_CODE (loop->n2) == TREE_VEC)
457 : : {
458 : 1273 : if (loop->outer)
459 : 742 : gcc_assert (TREE_VEC_ELT (loop->n2, 0)
460 : : == gimple_omp_for_index (for_stmt, i - loop->outer));
461 : : else
462 : 690 : for (int j = i - 1; j >= 0; j--)
463 : 690 : if (TREE_VEC_ELT (loop->n2, 0) == gimple_omp_for_index (for_stmt, j))
464 : : {
465 : 531 : loop->outer = i - j;
466 : 531 : if (loops != NULL)
467 : 241 : loops[j].non_rect_referenced = true;
468 : 531 : if (fd->first_nonrect == -1 || fd->first_nonrect > j)
469 : 525 : fd->first_nonrect = j;
470 : : break;
471 : : }
472 : 1273 : gcc_assert (loop->outer);
473 : 1273 : loop->m2 = TREE_VEC_ELT (loop->n2, 1);
474 : 1273 : loop->n2 = TREE_VEC_ELT (loop->n2, 2);
475 : 1273 : fd->non_rect = true;
476 : 1273 : fd->last_nonrect = i;
477 : : }
478 : :
479 : 189130 : t = gimple_omp_for_incr (for_stmt, i);
480 : 189130 : gcc_assert (TREE_OPERAND (t, 0) == var);
481 : 189130 : loop->step = omp_get_for_step_from_incr (loc, t);
482 : :
483 : 189130 : omp_adjust_for_condition (loc, &loop->cond_code, &loop->n2, loop->v,
484 : : loop->step);
485 : :
486 : 189130 : if (simd
487 : 149408 : || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
488 : 109985 : && !fd->have_ordered))
489 : : {
490 : 147996 : if (fd->collapse == 1 && !fd->tiling)
491 : 73186 : iter_type = TREE_TYPE (loop->v);
492 : 74810 : else if (i == 0
493 : 74810 : || TYPE_PRECISION (iter_type)
494 : 48313 : < TYPE_PRECISION (TREE_TYPE (loop->v)))
495 : : {
496 : 37374 : if (TREE_CODE (iter_type) == BITINT_TYPE
497 : 37374 : || TREE_CODE (TREE_TYPE (loop->v)) == BITINT_TYPE)
498 : 2 : iter_type
499 : 2 : = build_bitint_type (TYPE_PRECISION (TREE_TYPE (loop->v)),
500 : : 1);
501 : : else
502 : 37372 : iter_type
503 : : = build_nonstandard_integer_type
504 : 37372 : (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
505 : : }
506 : : }
507 : 41134 : else if (iter_type != long_long_unsigned_type_node)
508 : : {
509 : 37674 : if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
510 : : iter_type = long_long_unsigned_type_node;
511 : 35712 : else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
512 : 35712 : && TYPE_PRECISION (TREE_TYPE (loop->v))
513 : 6284 : >= TYPE_PRECISION (iter_type))
514 : : {
515 : 2318 : tree n;
516 : :
517 : 2318 : if (loop->cond_code == LT_EXPR)
518 : 450 : n = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
519 : : loop->n2, loop->step);
520 : : else
521 : 1868 : n = loop->n1;
522 : 2318 : if (loop->m1
523 : 2318 : || loop->m2
524 : 2318 : || TREE_CODE (n) != INTEGER_CST
525 : 4282 : || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
526 : 2242 : iter_type = long_long_unsigned_type_node;
527 : : }
528 : 33394 : else if (TYPE_PRECISION (TREE_TYPE (loop->v))
529 : 33394 : > TYPE_PRECISION (iter_type))
530 : : {
531 : 0 : tree n1, n2;
532 : :
533 : 0 : if (loop->cond_code == LT_EXPR)
534 : : {
535 : 0 : n1 = loop->n1;
536 : 0 : n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
537 : : loop->n2, loop->step);
538 : : }
539 : : else
540 : : {
541 : 0 : n1 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (loop->v),
542 : : loop->n2, loop->step);
543 : 0 : n2 = loop->n1;
544 : : }
545 : 0 : if (loop->m1
546 : 0 : || loop->m2
547 : 0 : || TREE_CODE (n1) != INTEGER_CST
548 : 0 : || TREE_CODE (n2) != INTEGER_CST
549 : 0 : || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
550 : 0 : || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
551 : 0 : iter_type = long_long_unsigned_type_node;
552 : : }
553 : : }
554 : :
555 : 189130 : if (i >= fd->collapse)
556 : 1802 : continue;
557 : :
558 : 187328 : if (collapse_count && *collapse_count == NULL)
559 : : {
560 : 31749 : if (count && integer_zerop (count))
561 : 2240 : continue;
562 : 29509 : tree n1first = NULL_TREE, n2first = NULL_TREE;
563 : 29509 : tree n1last = NULL_TREE, n2last = NULL_TREE;
564 : 29509 : tree ostep = NULL_TREE;
565 : 29509 : if (loop->m1 || loop->m2)
566 : : {
567 : 911 : if (count == NULL_TREE)
568 : 645 : continue;
569 : 266 : if (single_nonrect == -1
570 : 247 : || (loop->m1 && TREE_CODE (loop->m1) != INTEGER_CST)
571 : 206 : || (loop->m2 && TREE_CODE (loop->m2) != INTEGER_CST)
572 : 190 : || TREE_CODE (loop->n1) != INTEGER_CST
573 : 186 : || TREE_CODE (loop->n2) != INTEGER_CST
574 : 182 : || TREE_CODE (loop->step) != INTEGER_CST)
575 : : {
576 : 84 : count = NULL_TREE;
577 : 84 : continue;
578 : : }
579 : 182 : tree var = gimple_omp_for_initial (for_stmt, single_nonrect);
580 : 182 : tree itype = TREE_TYPE (var);
581 : 182 : tree first = gimple_omp_for_initial (for_stmt, single_nonrect);
582 : 182 : t = gimple_omp_for_incr (for_stmt, single_nonrect);
583 : 182 : ostep = omp_get_for_step_from_incr (loc, t);
584 : 182 : t = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
585 : : single_nonrect_count,
586 : : build_one_cst (long_long_unsigned_type_node));
587 : 182 : t = fold_convert (itype, t);
588 : 182 : first = fold_convert (itype, first);
589 : 182 : ostep = fold_convert (itype, ostep);
590 : 182 : tree last = fold_binary (PLUS_EXPR, itype, first,
591 : : fold_binary (MULT_EXPR, itype, t,
592 : : ostep));
593 : 182 : if (TREE_CODE (first) != INTEGER_CST
594 : 182 : || TREE_CODE (last) != INTEGER_CST)
595 : : {
596 : 0 : count = NULL_TREE;
597 : 0 : continue;
598 : : }
599 : 182 : if (loop->m1)
600 : : {
601 : 115 : tree m1 = fold_convert (itype, loop->m1);
602 : 115 : tree n1 = fold_convert (itype, loop->n1);
603 : 115 : n1first = fold_binary (PLUS_EXPR, itype,
604 : : fold_binary (MULT_EXPR, itype,
605 : : first, m1), n1);
606 : 115 : n1last = fold_binary (PLUS_EXPR, itype,
607 : : fold_binary (MULT_EXPR, itype,
608 : : last, m1), n1);
609 : : }
610 : : else
611 : 67 : n1first = n1last = loop->n1;
612 : 182 : if (loop->m2)
613 : : {
614 : 136 : tree n2 = fold_convert (itype, loop->n2);
615 : 136 : tree m2 = fold_convert (itype, loop->m2);
616 : 136 : n2first = fold_binary (PLUS_EXPR, itype,
617 : : fold_binary (MULT_EXPR, itype,
618 : : first, m2), n2);
619 : 136 : n2last = fold_binary (PLUS_EXPR, itype,
620 : : fold_binary (MULT_EXPR, itype,
621 : : last, m2), n2);
622 : : }
623 : : else
624 : 46 : n2first = n2last = loop->n2;
625 : 182 : n1first = fold_convert (TREE_TYPE (loop->v), n1first);
626 : 182 : n2first = fold_convert (TREE_TYPE (loop->v), n2first);
627 : 182 : n1last = fold_convert (TREE_TYPE (loop->v), n1last);
628 : 182 : n2last = fold_convert (TREE_TYPE (loop->v), n2last);
629 : 182 : t = fold_binary (loop->cond_code, boolean_type_node,
630 : : n1first, n2first);
631 : 182 : tree t2 = fold_binary (loop->cond_code, boolean_type_node,
632 : : n1last, n2last);
633 : 182 : if (t && t2 && integer_nonzerop (t) && integer_nonzerop (t2))
634 : : /* All outer loop iterators have at least one inner loop
635 : : iteration. Try to compute the count at compile time. */
636 : : t = NULL_TREE;
637 : 103 : else if (t && t2 && integer_zerop (t) && integer_zerop (t2))
638 : : /* No iterations of the inner loop. count will be set to
639 : : zero cst below. */;
640 : 95 : else if (TYPE_UNSIGNED (itype)
641 : 95 : || t == NULL_TREE
642 : 95 : || t2 == NULL_TREE
643 : 95 : || TREE_CODE (t) != INTEGER_CST
644 : 190 : || TREE_CODE (t2) != INTEGER_CST)
645 : : {
646 : : /* Punt (for now). */
647 : 0 : count = NULL_TREE;
648 : 0 : continue;
649 : : }
650 : : else
651 : : {
652 : : /* Some iterations of the outer loop have zero iterations
653 : : of the inner loop, while others have at least one.
654 : : In this case, we need to adjust one of those outer
655 : : loop bounds. If ADJ_FIRST, we need to adjust outer n1
656 : : (first), otherwise outer n2 (last). */
657 : 95 : bool adj_first = integer_zerop (t);
658 : 95 : tree n1 = fold_convert (itype, loop->n1);
659 : 95 : tree n2 = fold_convert (itype, loop->n2);
660 : 95 : tree m1 = loop->m1 ? fold_convert (itype, loop->m1)
661 : 25 : : build_zero_cst (itype);
662 : 95 : tree m2 = loop->m2 ? fold_convert (itype, loop->m2)
663 : 11 : : build_zero_cst (itype);
664 : 95 : t = fold_binary (MINUS_EXPR, itype, n1, n2);
665 : 95 : t2 = fold_binary (MINUS_EXPR, itype, m2, m1);
666 : 95 : t = fold_binary (TRUNC_DIV_EXPR, itype, t, t2);
667 : 95 : t2 = fold_binary (MINUS_EXPR, itype, t, first);
668 : 95 : t2 = fold_binary (TRUNC_MOD_EXPR, itype, t2, ostep);
669 : 95 : t = fold_binary (MINUS_EXPR, itype, t, t2);
670 : 95 : tree n1cur
671 : 95 : = fold_binary (PLUS_EXPR, itype, n1,
672 : : fold_binary (MULT_EXPR, itype, m1, t));
673 : 95 : tree n2cur
674 : 95 : = fold_binary (PLUS_EXPR, itype, n2,
675 : : fold_binary (MULT_EXPR, itype, m2, t));
676 : 95 : t2 = fold_binary (loop->cond_code, boolean_type_node,
677 : : n1cur, n2cur);
678 : 95 : tree t3 = fold_binary (MULT_EXPR, itype, m1, ostep);
679 : 95 : tree t4 = fold_binary (MULT_EXPR, itype, m2, ostep);
680 : 95 : tree diff;
681 : 95 : if (adj_first)
682 : : {
683 : 67 : tree new_first;
684 : 67 : if (integer_nonzerop (t2))
685 : : {
686 : 6 : new_first = t;
687 : 6 : n1first = n1cur;
688 : 6 : n2first = n2cur;
689 : 6 : if (flag_checking)
690 : : {
691 : 6 : t3 = fold_binary (MINUS_EXPR, itype, n1cur, t3);
692 : 6 : t4 = fold_binary (MINUS_EXPR, itype, n2cur, t4);
693 : 6 : t3 = fold_binary (loop->cond_code,
694 : : boolean_type_node, t3, t4);
695 : 6 : gcc_assert (integer_zerop (t3));
696 : : }
697 : : }
698 : : else
699 : : {
700 : 61 : t3 = fold_binary (PLUS_EXPR, itype, n1cur, t3);
701 : 61 : t4 = fold_binary (PLUS_EXPR, itype, n2cur, t4);
702 : 61 : new_first = fold_binary (PLUS_EXPR, itype, t, ostep);
703 : 61 : n1first = t3;
704 : 61 : n2first = t4;
705 : 61 : if (flag_checking)
706 : : {
707 : 61 : t3 = fold_binary (loop->cond_code,
708 : : boolean_type_node, t3, t4);
709 : 61 : gcc_assert (integer_nonzerop (t3));
710 : : }
711 : : }
712 : 67 : diff = fold_binary (MINUS_EXPR, itype, new_first, first);
713 : 67 : first = new_first;
714 : 67 : fd->adjn1 = first;
715 : : }
716 : : else
717 : : {
718 : 28 : tree new_last;
719 : 28 : if (integer_zerop (t2))
720 : : {
721 : 11 : t3 = fold_binary (MINUS_EXPR, itype, n1cur, t3);
722 : 11 : t4 = fold_binary (MINUS_EXPR, itype, n2cur, t4);
723 : 11 : new_last = fold_binary (MINUS_EXPR, itype, t, ostep);
724 : 11 : n1last = t3;
725 : 11 : n2last = t4;
726 : 11 : if (flag_checking)
727 : : {
728 : 11 : t3 = fold_binary (loop->cond_code,
729 : : boolean_type_node, t3, t4);
730 : 11 : gcc_assert (integer_nonzerop (t3));
731 : : }
732 : : }
733 : : else
734 : : {
735 : 17 : new_last = t;
736 : 17 : n1last = n1cur;
737 : 17 : n2last = n2cur;
738 : 17 : if (flag_checking)
739 : : {
740 : 17 : t3 = fold_binary (PLUS_EXPR, itype, n1cur, t3);
741 : 17 : t4 = fold_binary (PLUS_EXPR, itype, n2cur, t4);
742 : 17 : t3 = fold_binary (loop->cond_code,
743 : : boolean_type_node, t3, t4);
744 : 17 : gcc_assert (integer_zerop (t3));
745 : : }
746 : : }
747 : 28 : diff = fold_binary (MINUS_EXPR, itype, last, new_last);
748 : : }
749 : 95 : if (TYPE_UNSIGNED (itype)
750 : 95 : && single_nonrect_cond_code == GT_EXPR)
751 : 0 : diff = fold_binary (TRUNC_DIV_EXPR, itype,
752 : : fold_unary (NEGATE_EXPR, itype, diff),
753 : : fold_unary (NEGATE_EXPR, itype,
754 : : ostep));
755 : : else
756 : 95 : diff = fold_binary (TRUNC_DIV_EXPR, itype, diff, ostep);
757 : 95 : diff = fold_convert (long_long_unsigned_type_node, diff);
758 : 95 : single_nonrect_count
759 : 95 : = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
760 : : single_nonrect_count, diff);
761 : 95 : t = NULL_TREE;
762 : : }
763 : : }
764 : : else
765 : 28598 : t = fold_binary (loop->cond_code, boolean_type_node,
766 : : fold_convert (TREE_TYPE (loop->v), loop->n1),
767 : : fold_convert (TREE_TYPE (loop->v), loop->n2));
768 : 28780 : if (t && integer_zerop (t))
769 : 2248 : count = build_zero_cst (long_long_unsigned_type_node);
770 : 26532 : else if ((i == 0 || count != NULL_TREE)
771 : 16843 : && (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
772 : 1202 : || TREE_CODE (TREE_TYPE (loop->v)) == BITINT_TYPE)
773 : 15642 : && TREE_CONSTANT (loop->n1)
774 : 11641 : && TREE_CONSTANT (loop->n2)
775 : 37188 : && TREE_CODE (loop->step) == INTEGER_CST)
776 : : {
777 : 10634 : tree itype = TREE_TYPE (loop->v);
778 : :
779 : 10634 : if (POINTER_TYPE_P (itype))
780 : 0 : itype = signed_type_for (itype);
781 : 13002 : t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
782 : 10634 : t = fold_build2 (PLUS_EXPR, itype,
783 : : fold_convert (itype, loop->step), t);
784 : 10634 : tree n1 = loop->n1;
785 : 10634 : tree n2 = loop->n2;
786 : 10634 : if (loop->m1 || loop->m2)
787 : : {
788 : 174 : gcc_assert (single_nonrect != -1);
789 : : n1 = n1first;
790 : : n2 = n2first;
791 : : }
792 : 10634 : t = fold_build2 (PLUS_EXPR, itype, t, fold_convert (itype, n2));
793 : 10634 : t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
794 : 10634 : tree step = fold_convert_loc (loc, itype, loop->step);
795 : 10634 : if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
796 : 2254 : t = fold_build2 (TRUNC_DIV_EXPR, itype,
797 : : fold_build1 (NEGATE_EXPR, itype, t),
798 : : fold_build1 (NEGATE_EXPR, itype, step));
799 : : else
800 : 8380 : t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
801 : 10634 : tree llutype = long_long_unsigned_type_node;
802 : 10634 : t = fold_convert (llutype, t);
803 : 10634 : if (loop->m1 || loop->m2)
804 : : {
805 : : /* t is number of iterations of inner loop at either first
806 : : or last value of the outer iterator (the one with fewer
807 : : iterations).
808 : : Compute t2 = ((m2 - m1) * ostep) / step
809 : : and niters = outer_count * t
810 : : + t2 * ((outer_count - 1) * outer_count / 2)
811 : : */
812 : 174 : tree m1 = loop->m1 ? loop->m1 : integer_zero_node;
813 : 174 : tree m2 = loop->m2 ? loop->m2 : integer_zero_node;
814 : 174 : m1 = fold_convert (itype, m1);
815 : 174 : m2 = fold_convert (itype, m2);
816 : 174 : tree t2 = fold_build2 (MINUS_EXPR, itype, m2, m1);
817 : 174 : t2 = fold_build2 (MULT_EXPR, itype, t2, ostep);
818 : 174 : if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
819 : 0 : t2 = fold_build2 (TRUNC_DIV_EXPR, itype,
820 : : fold_build1 (NEGATE_EXPR, itype, t2),
821 : : fold_build1 (NEGATE_EXPR, itype, step));
822 : : else
823 : 174 : t2 = fold_build2 (TRUNC_DIV_EXPR, itype, t2, step);
824 : 174 : t2 = fold_convert (llutype, t2);
825 : 174 : fd->first_inner_iterations = t;
826 : 174 : fd->factor = t2;
827 : 174 : t = fold_build2 (MULT_EXPR, llutype, t,
828 : : single_nonrect_count);
829 : 174 : tree t3 = fold_build2 (MINUS_EXPR, llutype,
830 : : single_nonrect_count,
831 : : build_one_cst (llutype));
832 : 174 : t3 = fold_build2 (MULT_EXPR, llutype, t3,
833 : : single_nonrect_count);
834 : 174 : t3 = fold_build2 (TRUNC_DIV_EXPR, llutype, t3,
835 : : build_int_cst (llutype, 2));
836 : 174 : t2 = fold_build2 (MULT_EXPR, llutype, t2, t3);
837 : 174 : t = fold_build2 (PLUS_EXPR, llutype, t, t2);
838 : : }
839 : 10634 : if (i == single_nonrect)
840 : : {
841 : 247 : if (integer_zerop (t) || TREE_CODE (t) != INTEGER_CST)
842 : : count = t;
843 : : else
844 : : {
845 : 247 : single_nonrect_count = t;
846 : 247 : single_nonrect_cond_code = loop->cond_code;
847 : 247 : if (count == NULL_TREE)
848 : 246 : count = build_one_cst (llutype);
849 : : }
850 : : }
851 : 10387 : else if (count != NULL_TREE)
852 : 4144 : count = fold_build2 (MULT_EXPR, llutype, count, t);
853 : : else
854 : : count = t;
855 : 10634 : if (TREE_CODE (count) != INTEGER_CST)
856 : 0 : count = NULL_TREE;
857 : : }
858 : 15898 : else if (count && !integer_zerop (count))
859 : : count = NULL_TREE;
860 : : }
861 : : }
862 : :
863 : 124973 : if (count
864 : 124973 : && !simd
865 : 3989 : && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
866 : 3230 : || fd->have_ordered))
867 : : {
868 : 855 : if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
869 : 0 : iter_type = long_long_unsigned_type_node;
870 : : else
871 : 855 : iter_type = long_integer_type_node;
872 : : }
873 : 124118 : else if (collapse_iter && *collapse_iter != NULL)
874 : 22753 : iter_type = TREE_TYPE (*collapse_iter);
875 : 124973 : fd->iter_type = iter_type;
876 : 124973 : if (collapse_iter && *collapse_iter == NULL)
877 : 11453 : *collapse_iter = create_tmp_var (iter_type, ".iter");
878 : 124973 : if (collapse_count && *collapse_count == NULL)
879 : : {
880 : 11453 : if (count)
881 : : {
882 : 5160 : *collapse_count = fold_convert_loc (loc, iter_type, count);
883 : 5160 : if (fd->first_inner_iterations && fd->factor)
884 : : {
885 : 174 : t = make_tree_vec (4);
886 : 174 : TREE_VEC_ELT (t, 0) = *collapse_count;
887 : 174 : TREE_VEC_ELT (t, 1) = fd->first_inner_iterations;
888 : 174 : TREE_VEC_ELT (t, 2) = fd->factor;
889 : 174 : TREE_VEC_ELT (t, 3) = fd->adjn1;
890 : 174 : *collapse_count = t;
891 : : }
892 : : }
893 : : else
894 : 6293 : *collapse_count = create_tmp_var (iter_type, ".count");
895 : : }
896 : :
897 : 124973 : if (fd->collapse > 1 || fd->tiling || (fd->ordered && loops))
898 : : {
899 : 34202 : fd->loop.v = *collapse_iter;
900 : 34202 : fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
901 : 34202 : fd->loop.n2 = *collapse_count;
902 : 34202 : if (TREE_CODE (fd->loop.n2) == TREE_VEC)
903 : : {
904 : 377 : gcc_assert (fd->non_rect);
905 : 377 : fd->first_inner_iterations = TREE_VEC_ELT (fd->loop.n2, 1);
906 : 377 : fd->factor = TREE_VEC_ELT (fd->loop.n2, 2);
907 : 377 : fd->adjn1 = TREE_VEC_ELT (fd->loop.n2, 3);
908 : 377 : fd->loop.n2 = TREE_VEC_ELT (fd->loop.n2, 0);
909 : : }
910 : 34202 : fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
911 : 34202 : fd->loop.m1 = NULL_TREE;
912 : 34202 : fd->loop.m2 = NULL_TREE;
913 : 34202 : fd->loop.outer = 0;
914 : 34202 : fd->loop.cond_code = LT_EXPR;
915 : : }
916 : 90559 : else if (loops)
917 : 34112 : loops[0] = fd->loop;
918 : 124973 : }
919 : :
920 : : /* Build a call to GOMP_barrier. */
921 : :
922 : : gimple *
923 : 4701 : omp_build_barrier (tree lhs)
924 : : {
925 : 9344 : tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
926 : : : BUILT_IN_GOMP_BARRIER);
927 : 4701 : gcall *g = gimple_build_call (fndecl, 0);
928 : 4701 : if (lhs)
929 : 58 : gimple_call_set_lhs (g, lhs);
930 : 4701 : return g;
931 : : }
932 : :
933 : : /* Find OMP_FOR resp. OMP_SIMD with non-NULL OMP_FOR_INIT. Also, fill in pdata
934 : : array, pdata[0] non-NULL if there is anything non-trivial in between,
935 : : pdata[1] is address of OMP_PARALLEL in between if any, pdata[2] is address
936 : : of OMP_FOR in between if any and pdata[3] is address of the inner
937 : : OMP_FOR/OMP_SIMD. */
938 : :
939 : : tree
940 : 109150 : find_combined_omp_for (tree *tp, int *walk_subtrees, void *data)
941 : : {
942 : 109150 : tree **pdata = (tree **) data;
943 : 109150 : *walk_subtrees = 0;
944 : 109150 : switch (TREE_CODE (*tp))
945 : : {
946 : 11794 : case OMP_FOR:
947 : 11794 : if (OMP_FOR_INIT (*tp) != NULL_TREE)
948 : : {
949 : 5986 : pdata[3] = tp;
950 : 5986 : return *tp;
951 : : }
952 : 5808 : pdata[2] = tp;
953 : 5808 : *walk_subtrees = 1;
954 : 5808 : break;
955 : 15263 : case OMP_SIMD:
956 : 15263 : if (OMP_FOR_INIT (*tp) != NULL_TREE)
957 : : {
958 : 15263 : pdata[3] = tp;
959 : 15263 : return *tp;
960 : : }
961 : : break;
962 : 46222 : case BIND_EXPR:
963 : 46222 : if (BIND_EXPR_VARS (*tp)
964 : 46222 : || (BIND_EXPR_BLOCK (*tp)
965 : 40697 : && BLOCK_VARS (BIND_EXPR_BLOCK (*tp))))
966 : 5087 : pdata[0] = tp;
967 : 46222 : *walk_subtrees = 1;
968 : 46222 : break;
969 : 8500 : case STATEMENT_LIST:
970 : 8500 : if (!tsi_one_before_end_p (tsi_start (*tp)))
971 : 242 : pdata[0] = tp;
972 : 8500 : *walk_subtrees = 1;
973 : 8500 : break;
974 : 218 : case TRY_FINALLY_EXPR:
975 : 218 : case CLEANUP_POINT_EXPR:
976 : 218 : pdata[0] = tp;
977 : 218 : *walk_subtrees = 1;
978 : 218 : break;
979 : 11822 : case OMP_PARALLEL:
980 : 11822 : pdata[1] = tp;
981 : 11822 : *walk_subtrees = 1;
982 : 11822 : break;
983 : : default:
984 : : break;
985 : : }
986 : : return NULL_TREE;
987 : : }
988 : :
989 : : /* Return maximum possible vectorization factor for the target. */
990 : :
991 : : poly_uint64
992 : 29396 : omp_max_vf (void)
993 : : {
994 : 29396 : if (!optimize
995 : 28069 : || optimize_debug
996 : 28069 : || !flag_tree_loop_optimize
997 : 28068 : || (!flag_tree_loop_vectorize
998 : 576 : && OPTION_SET_P (flag_tree_loop_vectorize)))
999 : 1332 : return 1;
1000 : :
1001 : 28064 : auto_vector_modes modes;
1002 : 28064 : targetm.vectorize.autovectorize_vector_modes (&modes, true);
1003 : 28064 : if (!modes.is_empty ())
1004 : : {
1005 : : poly_uint64 vf = 0;
1006 : 117103 : for (unsigned int i = 0; i < modes.length (); ++i)
1007 : : /* The returned modes use the smallest element size (and thus
1008 : : the largest nunits) for the vectorization approach that they
1009 : : represent. */
1010 : 178086 : vf = ordered_max (vf, GET_MODE_NUNITS (modes[i]));
1011 : 28060 : return vf;
1012 : : }
1013 : :
1014 : 4 : machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
1015 : 4 : if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
1016 : 0 : return GET_MODE_NUNITS (vqimode);
1017 : :
1018 : 4 : return 1;
1019 : 28064 : }
1020 : :
1021 : : /* Return maximum SIMT width if offloading may target SIMT hardware. */
1022 : :
1023 : : int
1024 : 3624 : omp_max_simt_vf (void)
1025 : : {
1026 : 3624 : if (!optimize)
1027 : : return 0;
1028 : : if (ENABLE_OFFLOADING)
1029 : : for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
1030 : : {
1031 : : if (startswith (c, "nvptx"))
1032 : : return 32;
1033 : : else if ((c = strchr (c, ':')))
1034 : : c++;
1035 : : }
1036 : : return 0;
1037 : : }
1038 : :
1039 : : /* Store the construct selectors as tree codes from last to first.
1040 : : CTX is a list of trait selectors, nconstructs must be equal to its
1041 : : length, and the array CONSTRUCTS holds the output. */
1042 : :
1043 : : void
1044 : 338 : omp_construct_traits_to_codes (tree ctx, int nconstructs,
1045 : : enum tree_code *constructs)
1046 : : {
1047 : 338 : int i = nconstructs - 1;
1048 : :
1049 : : /* Order must match the OMP_TRAIT_CONSTRUCT_* enumerators in
1050 : : enum omp_ts_code. */
1051 : 338 : static enum tree_code code_map[]
1052 : : = { OMP_TARGET, OMP_TEAMS, OMP_PARALLEL, OMP_FOR, OMP_SIMD };
1053 : :
1054 : 981 : for (tree ts = ctx; ts; ts = TREE_CHAIN (ts), i--)
1055 : : {
1056 : 643 : enum omp_ts_code sel = OMP_TS_CODE (ts);
1057 : 643 : int j = (int)sel - (int)OMP_TRAIT_CONSTRUCT_TARGET;
1058 : 643 : gcc_assert (j >= 0 && (unsigned int) j < ARRAY_SIZE (code_map));
1059 : 643 : constructs[i] = code_map[j];
1060 : : }
1061 : 338 : gcc_assert (i == -1);
1062 : 338 : }
1063 : :
1064 : : /* Return true if PROP is possibly present in one of the offloading target's
1065 : : OpenMP contexts. The format of PROPS string is always offloading target's
1066 : : name terminated by '\0', followed by properties for that offloading
1067 : : target separated by '\0' and terminated by another '\0'. The strings
1068 : : are created from omp-device-properties installed files of all configured
1069 : : offloading targets. */
1070 : :
1071 : : static bool
1072 : 0 : omp_offload_device_kind_arch_isa (const char *props, const char *prop)
1073 : : {
1074 : 0 : const char *names = getenv ("OFFLOAD_TARGET_NAMES");
1075 : 0 : if (names == NULL || *names == '\0')
1076 : : return false;
1077 : 0 : while (*props != '\0')
1078 : : {
1079 : 0 : size_t name_len = strlen (props);
1080 : 0 : bool matches = false;
1081 : 0 : for (const char *c = names; c; )
1082 : : {
1083 : 0 : if (strncmp (props, c, name_len) == 0
1084 : 0 : && (c[name_len] == '\0'
1085 : : || c[name_len] == ':'
1086 : : || c[name_len] == '='))
1087 : : {
1088 : : matches = true;
1089 : : break;
1090 : : }
1091 : 0 : else if ((c = strchr (c, ':')))
1092 : 0 : c++;
1093 : : }
1094 : 0 : props = props + name_len + 1;
1095 : 0 : while (*props != '\0')
1096 : : {
1097 : 0 : if (matches && strcmp (props, prop) == 0)
1098 : : return true;
1099 : 0 : props = strchr (props, '\0') + 1;
1100 : : }
1101 : 0 : props++;
1102 : : }
1103 : : return false;
1104 : : }
1105 : :
1106 : : /* Return true if the current code location is or might be offloaded.
1107 : : Return true in declare target functions, or when nested in a target
1108 : : region or when unsure, return false otherwise. */
1109 : :
1110 : : static bool
1111 : 0 : omp_maybe_offloaded (void)
1112 : : {
1113 : 0 : if (!ENABLE_OFFLOADING)
1114 : 0 : return false;
1115 : : const char *names = getenv ("OFFLOAD_TARGET_NAMES");
1116 : : if (names == NULL || *names == '\0')
1117 : : return false;
1118 : :
1119 : : if (symtab->state == PARSING)
1120 : : /* Maybe. */
1121 : : return true;
1122 : : if (cfun && cfun->after_inlining)
1123 : : return false;
1124 : : if (current_function_decl
1125 : : && lookup_attribute ("omp declare target",
1126 : : DECL_ATTRIBUTES (current_function_decl)))
1127 : : return true;
1128 : : if (cfun && (cfun->curr_properties & PROP_gimple_any) == 0)
1129 : : {
1130 : : enum tree_code construct = OMP_TARGET;
1131 : : if (omp_construct_selector_matches (&construct, 1, NULL))
1132 : : return true;
1133 : : }
1134 : : return false;
1135 : : }
1136 : :
1137 : : /* Lookup tables for context selectors. */
1138 : : const char *omp_tss_map[] =
1139 : : {
1140 : : "construct",
1141 : : "device",
1142 : : "target_device",
1143 : : "implementation",
1144 : : "user",
1145 : : NULL
1146 : : };
1147 : :
1148 : : /* Arrays of property candidates must be null-terminated. */
1149 : : static const char *const kind_properties[] =
1150 : : { "host", "nohost", "cpu", "gpu", "fpga", "any", NULL };
1151 : : static const char *const vendor_properties[] =
1152 : : { "amd", "arm", "bsc", "cray", "fujitsu", "gnu", "hpe", "ibm", "intel",
1153 : : "llvm", "nvidia", "pgi", "ti", "unknown", NULL };
1154 : : static const char *const extension_properties[] =
1155 : : { NULL };
1156 : : static const char *const atomic_default_mem_order_properties[] =
1157 : : { "seq_cst", "relaxed", "acq_rel", "acquire", "release", NULL };
1158 : :
1159 : : struct omp_ts_info omp_ts_map[] =
1160 : : {
1161 : : { "kind",
1162 : : (1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
1163 : : OMP_TRAIT_PROPERTY_NAME_LIST, false,
1164 : : kind_properties
1165 : : },
1166 : : { "isa",
1167 : : (1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
1168 : : OMP_TRAIT_PROPERTY_NAME_LIST, false,
1169 : : NULL
1170 : : },
1171 : : { "arch",
1172 : : (1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
1173 : : OMP_TRAIT_PROPERTY_NAME_LIST, false,
1174 : : NULL
1175 : : },
1176 : : { "device_num",
1177 : : (1 << OMP_TRAIT_SET_TARGET_DEVICE),
1178 : : OMP_TRAIT_PROPERTY_DEV_NUM_EXPR, false,
1179 : : NULL
1180 : : },
1181 : : { "vendor",
1182 : : (1 << OMP_TRAIT_SET_IMPLEMENTATION),
1183 : : OMP_TRAIT_PROPERTY_NAME_LIST, true,
1184 : : vendor_properties,
1185 : : },
1186 : : { "extension",
1187 : : (1 << OMP_TRAIT_SET_IMPLEMENTATION),
1188 : : OMP_TRAIT_PROPERTY_NAME_LIST, true,
1189 : : extension_properties,
1190 : : },
1191 : : { "atomic_default_mem_order",
1192 : : (1 << OMP_TRAIT_SET_IMPLEMENTATION),
1193 : : OMP_TRAIT_PROPERTY_ID, true,
1194 : : atomic_default_mem_order_properties,
1195 : : },
1196 : : { "requires",
1197 : : (1 << OMP_TRAIT_SET_IMPLEMENTATION),
1198 : : OMP_TRAIT_PROPERTY_CLAUSE_LIST, true,
1199 : : NULL
1200 : : },
1201 : : { "unified_address",
1202 : : (1 << OMP_TRAIT_SET_IMPLEMENTATION),
1203 : : OMP_TRAIT_PROPERTY_NONE, true,
1204 : : NULL
1205 : : },
1206 : : { "unified_shared_memory",
1207 : : (1 << OMP_TRAIT_SET_IMPLEMENTATION),
1208 : : OMP_TRAIT_PROPERTY_NONE, true,
1209 : : NULL
1210 : : },
1211 : : { "self_maps",
1212 : : (1 << OMP_TRAIT_SET_IMPLEMENTATION),
1213 : : OMP_TRAIT_PROPERTY_NONE, true,
1214 : : NULL
1215 : : },
1216 : : { "dynamic_allocators",
1217 : : (1 << OMP_TRAIT_SET_IMPLEMENTATION),
1218 : : OMP_TRAIT_PROPERTY_NONE, true,
1219 : : NULL
1220 : : },
1221 : : { "reverse_offload",
1222 : : (1 << OMP_TRAIT_SET_IMPLEMENTATION),
1223 : : OMP_TRAIT_PROPERTY_NONE, true,
1224 : : NULL
1225 : : },
1226 : : { "condition",
1227 : : (1 << OMP_TRAIT_SET_USER),
1228 : : OMP_TRAIT_PROPERTY_BOOL_EXPR, true,
1229 : : NULL
1230 : : },
1231 : : { "target",
1232 : : (1 << OMP_TRAIT_SET_CONSTRUCT),
1233 : : OMP_TRAIT_PROPERTY_NONE, false,
1234 : : NULL
1235 : : },
1236 : : { "teams",
1237 : : (1 << OMP_TRAIT_SET_CONSTRUCT),
1238 : : OMP_TRAIT_PROPERTY_NONE, false,
1239 : : NULL
1240 : : },
1241 : : { "parallel",
1242 : : (1 << OMP_TRAIT_SET_CONSTRUCT),
1243 : : OMP_TRAIT_PROPERTY_NONE, false,
1244 : : NULL
1245 : : },
1246 : : { "for",
1247 : : (1 << OMP_TRAIT_SET_CONSTRUCT),
1248 : : OMP_TRAIT_PROPERTY_NONE, false,
1249 : : NULL
1250 : : },
1251 : : { "simd",
1252 : : (1 << OMP_TRAIT_SET_CONSTRUCT),
1253 : : OMP_TRAIT_PROPERTY_CLAUSE_LIST, false,
1254 : : NULL
1255 : : },
1256 : : { NULL, 0, OMP_TRAIT_PROPERTY_NONE, false, NULL } /* OMP_TRAIT_LAST */
1257 : : };
1258 : :
1259 : :
1260 : : /* Return a name from PROP, a property in selectors accepting
1261 : : name lists. */
1262 : :
1263 : : const char *
1264 : 6492 : omp_context_name_list_prop (tree prop)
1265 : : {
1266 : 6492 : gcc_assert (OMP_TP_NAME (prop) == OMP_TP_NAMELIST_NODE);
1267 : 6492 : tree val = OMP_TP_VALUE (prop);
1268 : 6492 : switch (TREE_CODE (val))
1269 : : {
1270 : 5053 : case IDENTIFIER_NODE:
1271 : 5053 : return IDENTIFIER_POINTER (val);
1272 : 1439 : case STRING_CST:
1273 : 1439 : {
1274 : 1439 : const char *ret = TREE_STRING_POINTER (val);
1275 : 2878 : if ((size_t) TREE_STRING_LENGTH (val)
1276 : 2572 : == strlen (ret) + (lang_GNU_Fortran () ? 0 : 1))
1277 : : return ret;
1278 : : return NULL;
1279 : : }
1280 : : default:
1281 : : return NULL;
1282 : : }
1283 : : }
1284 : :
1285 : : /* Diagnose errors in an OpenMP context selector, return CTX if
1286 : : it is correct or error_mark_node otherwise. */
1287 : :
1288 : : tree
1289 : 1522 : omp_check_context_selector (location_t loc, tree ctx)
1290 : : {
1291 : 1522 : bool tss_seen[OMP_TRAIT_SET_LAST], ts_seen[OMP_TRAIT_LAST];
1292 : :
1293 : 1522 : memset (tss_seen, 0, sizeof (tss_seen));
1294 : 3177 : for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
1295 : : {
1296 : 1755 : enum omp_tss_code tss_code = OMP_TSS_CODE (tss);
1297 : 1755 : bool saw_any_prop = false;
1298 : 1755 : bool saw_other_prop = false;
1299 : :
1300 : : /* We can parse this, but not handle it yet. */
1301 : 1755 : if (tss_code == OMP_TRAIT_SET_TARGET_DEVICE)
1302 : 0 : sorry_at (loc, "%<target_device%> selector set is not supported yet");
1303 : :
1304 : : /* Each trait-set-selector-name can only be specified once. */
1305 : 1755 : if (tss_seen[tss_code])
1306 : : {
1307 : 30 : error_at (loc, "selector set %qs specified more than once",
1308 : 30 : OMP_TSS_NAME (tss));
1309 : 30 : return error_mark_node;
1310 : : }
1311 : : else
1312 : 1725 : tss_seen[tss_code] = true;
1313 : :
1314 : 1725 : memset (ts_seen, 0, sizeof (ts_seen));
1315 : 3916 : for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
1316 : : {
1317 : 2241 : enum omp_ts_code ts_code = OMP_TS_CODE (ts);
1318 : :
1319 : : /* Ignore unknown traits. */
1320 : 2241 : if (ts_code == OMP_TRAIT_INVALID)
1321 : 73 : continue;
1322 : :
1323 : : /* Each trait-selector-name can only be specified once. */
1324 : 2168 : if (ts_seen[ts_code])
1325 : : {
1326 : 15 : error_at (loc,
1327 : : "selector %qs specified more than once in set %qs",
1328 : 15 : OMP_TS_NAME (ts),
1329 : 15 : OMP_TSS_NAME (tss));
1330 : 15 : return error_mark_node;
1331 : : }
1332 : : else
1333 : 2153 : ts_seen[ts_code] = true;
1334 : :
1335 : : /* If trait-property "any" is specified in the "kind"
1336 : : trait-selector of the "device" selector set or the
1337 : : "target_device" selector sets, no other trait-property
1338 : : may be specified in the same selector set. */
1339 : 2153 : if (ts_code == OMP_TRAIT_DEVICE_KIND)
1340 : 676 : for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
1341 : : {
1342 : 268 : const char *prop = omp_context_name_list_prop (p);
1343 : 268 : if (!prop)
1344 : 1 : continue;
1345 : 267 : else if (strcmp (prop, "any") == 0)
1346 : : saw_any_prop = true;
1347 : : else
1348 : 205 : saw_other_prop = true;
1349 : : }
1350 : : /* It seems slightly suspicious that the spec's language covers
1351 : : the device_num selector too, but
1352 : : target_device={device_num(whatever),kind(any)}
1353 : : is probably not terribly useful anyway. */
1354 : 1949 : else if (ts_code == OMP_TRAIT_DEVICE_ARCH
1355 : : || ts_code == OMP_TRAIT_DEVICE_ISA
1356 : 1949 : || ts_code == OMP_TRAIT_DEVICE_NUM)
1357 : 338 : saw_other_prop = true;
1358 : :
1359 : : /* Each trait-property can only be specified once in a trait-selector
1360 : : other than the construct selector set. FIXME: only handles
1361 : : name-list properties, not clause-list properties, since the
1362 : : "requires" selector is not implemented yet (PR 113067). */
1363 : 2153 : if (tss_code != OMP_TRAIT_SET_CONSTRUCT)
1364 : 3821 : for (tree p1 = OMP_TS_PROPERTIES (ts); p1; p1 = TREE_CHAIN (p1))
1365 : : {
1366 : 1559 : if (OMP_TP_NAME (p1) != OMP_TP_NAMELIST_NODE)
1367 : : break;
1368 : 1071 : const char *n1 = omp_context_name_list_prop (p1);
1369 : 1071 : if (!n1)
1370 : 2 : continue;
1371 : 1427 : for (tree p2 = TREE_CHAIN (p1); p2; p2 = TREE_CHAIN (p2))
1372 : : {
1373 : 388 : const char *n2 = omp_context_name_list_prop (p2);
1374 : 388 : if (!n2)
1375 : 0 : continue;
1376 : 388 : if (!strcmp (n1, n2))
1377 : : {
1378 : 30 : error_at (loc,
1379 : : "trait-property %qs specified more "
1380 : : "than once in %qs selector",
1381 : 30 : n1, OMP_TS_NAME (ts));
1382 : 30 : return error_mark_node;
1383 : : }
1384 : : }
1385 : : }
1386 : :
1387 : : /* Check for unknown properties. */
1388 : 2123 : if (omp_ts_map[ts_code].valid_properties == NULL)
1389 : 1535 : continue;
1390 : 1848 : for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
1391 : 2682 : for (unsigned j = 0; ; j++)
1392 : : {
1393 : 3359 : const char *candidate
1394 : 3359 : = omp_ts_map[ts_code].valid_properties[j];
1395 : 3359 : if (candidate == NULL)
1396 : : {
1397 : : /* We've reached the end of the candidate array. */
1398 : 69 : if (ts_code == OMP_TRAIT_IMPLEMENTATION_ADMO)
1399 : : /* FIXME: not sure why this is an error vs warnings
1400 : : for the others, + incorrect/unknown wording? */
1401 : : {
1402 : 5 : error_at (loc,
1403 : : "incorrect property %qs of %qs selector",
1404 : 5 : IDENTIFIER_POINTER (OMP_TP_NAME (p)),
1405 : : "atomic_default_mem_order");
1406 : 5 : return error_mark_node;
1407 : : }
1408 : 64 : if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE
1409 : 64 : && (TREE_CODE (OMP_TP_VALUE (p)) == STRING_CST))
1410 : 18 : warning_at (loc, OPT_Wopenmp,
1411 : : "unknown property %qE of %qs selector",
1412 : 9 : OMP_TP_VALUE (p),
1413 : 9 : OMP_TS_NAME (ts));
1414 : 55 : else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
1415 : 110 : warning_at (loc, OPT_Wopenmp,
1416 : : "unknown property %qs of %qs selector",
1417 : : omp_context_name_list_prop (p),
1418 : 55 : OMP_TS_NAME (ts));
1419 : 0 : else if (OMP_TP_NAME (p))
1420 : 0 : warning_at (loc, OPT_Wopenmp,
1421 : : "unknown property %qs of %qs selector",
1422 : 0 : IDENTIFIER_POINTER (OMP_TP_NAME (p)),
1423 : 0 : OMP_TS_NAME (ts));
1424 : : break;
1425 : : }
1426 : 3290 : else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
1427 : : /* Property-list traits. */
1428 : : {
1429 : 3054 : const char *str = omp_context_name_list_prop (p);
1430 : 3054 : if (str && !strcmp (str, candidate))
1431 : : break;
1432 : : }
1433 : 236 : else if (!strcmp (IDENTIFIER_POINTER (OMP_TP_NAME (p)),
1434 : : candidate))
1435 : : /* Identifier traits. */
1436 : : break;
1437 : 2682 : }
1438 : : }
1439 : :
1440 : 1675 : if (saw_any_prop && saw_other_prop)
1441 : : {
1442 : 20 : error_at (loc,
1443 : : "no other trait-property may be specified "
1444 : : "in the same selector set with %<kind(\"any\")%>");
1445 : 20 : return error_mark_node;
1446 : : }
1447 : : }
1448 : : return ctx;
1449 : : }
1450 : :
1451 : :
1452 : : /* Register VARIANT as variant of some base function marked with
1453 : : #pragma omp declare variant. CONSTRUCT is corresponding list of
1454 : : trait-selectors for the construct selector set. This is stashed as the
1455 : : value of the "omp declare variant variant" attribute on VARIANT. */
1456 : : void
1457 : 1285 : omp_mark_declare_variant (location_t loc, tree variant, tree construct)
1458 : : {
1459 : : /* Ignore this variant if it contains unknown construct selectors.
1460 : : It will never match, and the front ends have already issued a warning
1461 : : about it. */
1462 : 1893 : for (tree c = construct; c; c = TREE_CHAIN (c))
1463 : 664 : if (OMP_TS_CODE (c) == OMP_TRAIT_INVALID)
1464 : : return;
1465 : :
1466 : 1229 : tree attr = lookup_attribute ("omp declare variant variant",
1467 : 1229 : DECL_ATTRIBUTES (variant));
1468 : 1229 : if (attr == NULL_TREE)
1469 : : {
1470 : 761 : attr = tree_cons (get_identifier ("omp declare variant variant"),
1471 : : unshare_expr (construct),
1472 : 761 : DECL_ATTRIBUTES (variant));
1473 : 761 : DECL_ATTRIBUTES (variant) = attr;
1474 : 761 : return;
1475 : : }
1476 : 468 : if ((TREE_VALUE (attr) != NULL_TREE) != (construct != NULL_TREE)
1477 : 468 : || (construct != NULL_TREE
1478 : 54 : && omp_context_selector_set_compare (OMP_TRAIT_SET_CONSTRUCT,
1479 : 54 : TREE_VALUE (attr),
1480 : : construct)))
1481 : 44 : error_at (loc, "%qD used as a variant with incompatible %<construct%> "
1482 : : "selector sets", variant);
1483 : : }
1484 : :
1485 : :
1486 : : /* Constructors for context selectors. */
1487 : :
1488 : : tree
1489 : 1759 : make_trait_set_selector (enum omp_tss_code code, tree selectors, tree chain)
1490 : : {
1491 : 1759 : return tree_cons (build_int_cst (integer_type_node, code),
1492 : 1759 : selectors, chain);
1493 : : }
1494 : :
1495 : : tree
1496 : 2326 : make_trait_selector (enum omp_ts_code code, tree score, tree properties,
1497 : : tree chain)
1498 : : {
1499 : 2326 : if (score == NULL_TREE)
1500 : 1998 : return tree_cons (build_int_cst (integer_type_node, code),
1501 : : properties, chain);
1502 : : else
1503 : 328 : return tree_cons (build_int_cst (integer_type_node, code),
1504 : : tree_cons (OMP_TS_SCORE_NODE, score, properties),
1505 : : chain);
1506 : : }
1507 : :
1508 : : tree
1509 : 1628 : make_trait_property (tree name, tree value, tree chain)
1510 : : {
1511 : 1628 : return tree_cons (name, value, chain);
1512 : : }
1513 : :
1514 : : /* Return 1 if context selector matches the current OpenMP context, 0
1515 : : if it does not and -1 if it is unknown and need to be determined later.
1516 : : Some properties can be checked right away during parsing (this routine),
1517 : : others need to wait until the whole TU is parsed, others need to wait until
1518 : : IPA, others until vectorization. */
1519 : :
1520 : : int
1521 : 1951 : omp_context_selector_matches (tree ctx)
1522 : : {
1523 : 1951 : int ret = 1;
1524 : 3406 : for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
1525 : : {
1526 : 2212 : enum omp_tss_code set = OMP_TSS_CODE (tss);
1527 : 2212 : tree selectors = OMP_TSS_TRAIT_SELECTORS (tss);
1528 : :
1529 : : /* Immediately reject the match if there are any ignored
1530 : : selectors present. */
1531 : 5043 : for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
1532 : 2899 : if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
1533 : : return 0;
1534 : :
1535 : 2144 : if (set == OMP_TRAIT_SET_CONSTRUCT)
1536 : : {
1537 : : /* For now, ignore the construct set. While something can be
1538 : : determined already during parsing, we don't know until end of TU
1539 : : whether additional constructs aren't added through declare variant
1540 : : unless "omp declare variant variant" attribute exists already
1541 : : (so in most of the cases), and we'd need to maintain set of
1542 : : surrounding OpenMP constructs, which is better handled during
1543 : : gimplification. */
1544 : 607 : if (symtab->state == PARSING)
1545 : : {
1546 : 326 : ret = -1;
1547 : 326 : continue;
1548 : : }
1549 : :
1550 : 281 : int nconstructs = list_length (selectors);
1551 : 281 : enum tree_code *constructs = NULL;
1552 : 281 : if (nconstructs)
1553 : : {
1554 : : /* Even though this alloca appears in a loop over selector
1555 : : sets, it does not repeatedly grow the stack, because
1556 : : there can be only one construct selector set specified.
1557 : : This is enforced by omp_check_context_selector. */
1558 : 281 : constructs
1559 : 281 : = (enum tree_code *) alloca (nconstructs
1560 : : * sizeof (enum tree_code));
1561 : 281 : omp_construct_traits_to_codes (selectors, nconstructs,
1562 : : constructs);
1563 : : }
1564 : :
1565 : 281 : if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1566 : : {
1567 : 9 : if (!cfun->after_inlining)
1568 : : {
1569 : 0 : ret = -1;
1570 : 0 : continue;
1571 : : }
1572 : : int i;
1573 : 9 : for (i = 0; i < nconstructs; ++i)
1574 : 9 : if (constructs[i] == OMP_SIMD)
1575 : : break;
1576 : 9 : if (i < nconstructs)
1577 : : {
1578 : 9 : ret = -1;
1579 : 9 : continue;
1580 : : }
1581 : : /* If there is no simd, assume it is ok after IPA,
1582 : : constructs should have been checked before. */
1583 : 0 : continue;
1584 : 0 : }
1585 : :
1586 : 272 : int r = omp_construct_selector_matches (constructs, nconstructs,
1587 : : NULL);
1588 : 272 : if (r == 0)
1589 : : return 0;
1590 : 154 : if (r == -1)
1591 : 20 : ret = -1;
1592 : 154 : continue;
1593 : 154 : }
1594 : 2654 : for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
1595 : : {
1596 : 1688 : enum omp_ts_code sel = OMP_TS_CODE (ts);
1597 : 1688 : switch (sel)
1598 : : {
1599 : 303 : case OMP_TRAIT_IMPLEMENTATION_VENDOR:
1600 : 303 : if (set == OMP_TRAIT_SET_IMPLEMENTATION)
1601 : 785 : for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
1602 : : {
1603 : 318 : const char *prop = omp_context_name_list_prop (p);
1604 : 318 : if (prop == NULL)
1605 : : return 0;
1606 : 317 : if (!strcmp (prop, "gnu"))
1607 : 179 : continue;
1608 : : return 0;
1609 : : }
1610 : : break;
1611 : 30 : case OMP_TRAIT_IMPLEMENTATION_EXTENSION:
1612 : 30 : if (set == OMP_TRAIT_SET_IMPLEMENTATION)
1613 : : /* We don't support any extensions right now. */
1614 : : return 0;
1615 : : break;
1616 : 120 : case OMP_TRAIT_IMPLEMENTATION_ADMO:
1617 : 120 : if (set == OMP_TRAIT_SET_IMPLEMENTATION)
1618 : : {
1619 : 120 : if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1620 : : break;
1621 : :
1622 : 120 : enum omp_memory_order omo
1623 : : = ((enum omp_memory_order)
1624 : 120 : (omp_requires_mask
1625 : : & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER));
1626 : 120 : if (omo == OMP_MEMORY_ORDER_UNSPECIFIED)
1627 : : {
1628 : : /* We don't know yet, until end of TU. */
1629 : 65 : if (symtab->state == PARSING)
1630 : : {
1631 : : ret = -1;
1632 : : break;
1633 : : }
1634 : : else
1635 : : omo = OMP_MEMORY_ORDER_RELAXED;
1636 : : }
1637 : 55 : tree p = OMP_TS_PROPERTIES (ts);
1638 : 55 : const char *prop = IDENTIFIER_POINTER (OMP_TP_NAME (p));
1639 : 55 : if (!strcmp (prop, "relaxed")
1640 : 2 : && omo != OMP_MEMORY_ORDER_RELAXED)
1641 : : return 0;
1642 : 53 : else if (!strcmp (prop, "seq_cst")
1643 : 53 : && omo != OMP_MEMORY_ORDER_SEQ_CST)
1644 : : return 0;
1645 : 53 : else if (!strcmp (prop, "acq_rel")
1646 : 0 : && omo != OMP_MEMORY_ORDER_ACQ_REL)
1647 : : return 0;
1648 : 53 : else if (!strcmp (prop, "acquire")
1649 : 0 : && omo != OMP_MEMORY_ORDER_ACQUIRE)
1650 : : return 0;
1651 : 53 : else if (!strcmp (prop, "release")
1652 : 0 : && omo != OMP_MEMORY_ORDER_RELEASE)
1653 : : return 0;
1654 : : }
1655 : : break;
1656 : 167 : case OMP_TRAIT_DEVICE_ARCH:
1657 : 167 : if (set == OMP_TRAIT_SET_DEVICE)
1658 : 414 : for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
1659 : : {
1660 : 172 : const char *arch = omp_context_name_list_prop (p);
1661 : 172 : if (arch == NULL)
1662 : : return 0;
1663 : 172 : int r = 0;
1664 : 172 : if (targetm.omp.device_kind_arch_isa != NULL)
1665 : 172 : r = targetm.omp.device_kind_arch_isa (omp_device_arch,
1666 : : arch);
1667 : 172 : if (r == 0 || (r == -1 && symtab->state != PARSING))
1668 : : {
1669 : : /* If we are or might be in a target region or
1670 : : declare target function, need to take into account
1671 : : also offloading values. */
1672 : 92 : if (!omp_maybe_offloaded ())
1673 : 92 : return 0;
1674 : : if (ENABLE_OFFLOADING)
1675 : : {
1676 : : const char *arches = omp_offload_device_arch;
1677 : : if (omp_offload_device_kind_arch_isa (arches,
1678 : : arch))
1679 : : {
1680 : : ret = -1;
1681 : : continue;
1682 : : }
1683 : : }
1684 : : return 0;
1685 : : }
1686 : : else if (r == -1)
1687 : : ret = -1;
1688 : : /* If arch matches on the host, it still might not match
1689 : : in the offloading region. */
1690 : : else if (omp_maybe_offloaded ())
1691 : : ret = -1;
1692 : : }
1693 : : break;
1694 : 20 : case OMP_TRAIT_IMPLEMENTATION_UNIFIED_ADDRESS:
1695 : 20 : if (set == OMP_TRAIT_SET_IMPLEMENTATION)
1696 : : {
1697 : 20 : if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1698 : : break;
1699 : :
1700 : 20 : if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_ADDRESS) == 0)
1701 : : {
1702 : 20 : if (symtab->state == PARSING)
1703 : : ret = -1;
1704 : : else
1705 : : return 0;
1706 : : }
1707 : : }
1708 : : break;
1709 : 15 : case OMP_TRAIT_IMPLEMENTATION_UNIFIED_SHARED_MEMORY:
1710 : 15 : if (set == OMP_TRAIT_SET_IMPLEMENTATION)
1711 : : {
1712 : 15 : if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1713 : : break;
1714 : :
1715 : 15 : if ((omp_requires_mask
1716 : : & OMP_REQUIRES_UNIFIED_SHARED_MEMORY) == 0)
1717 : : {
1718 : 15 : if (symtab->state == PARSING)
1719 : : ret = -1;
1720 : : else
1721 : : return 0;
1722 : : }
1723 : : }
1724 : : break;
1725 : 5 : case OMP_TRAIT_IMPLEMENTATION_SELF_MAPS:
1726 : 5 : if (set == OMP_TRAIT_SET_IMPLEMENTATION)
1727 : : {
1728 : 5 : if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1729 : : break;
1730 : :
1731 : 5 : if ((omp_requires_mask
1732 : : & OMP_REQUIRES_SELF_MAPS) == 0)
1733 : : {
1734 : 5 : if (symtab->state == PARSING)
1735 : : ret = -1;
1736 : : else
1737 : : return 0;
1738 : : }
1739 : : }
1740 : : break;
1741 : 10 : case OMP_TRAIT_IMPLEMENTATION_DYNAMIC_ALLOCATORS:
1742 : 10 : if (set == OMP_TRAIT_SET_IMPLEMENTATION)
1743 : : {
1744 : 10 : if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1745 : : break;
1746 : :
1747 : 10 : if ((omp_requires_mask
1748 : : & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
1749 : : {
1750 : 10 : if (symtab->state == PARSING)
1751 : : ret = -1;
1752 : : else
1753 : : return 0;
1754 : : }
1755 : : }
1756 : : break;
1757 : 10 : case OMP_TRAIT_IMPLEMENTATION_REVERSE_OFFLOAD:
1758 : 10 : if (set == OMP_TRAIT_SET_IMPLEMENTATION)
1759 : : {
1760 : 10 : if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1761 : : break;
1762 : :
1763 : 10 : if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
1764 : : {
1765 : 10 : if (symtab->state == PARSING)
1766 : : ret = -1;
1767 : : else
1768 : : return 0;
1769 : : }
1770 : : }
1771 : : break;
1772 : 231 : case OMP_TRAIT_DEVICE_KIND:
1773 : 231 : if (set == OMP_TRAIT_SET_DEVICE)
1774 : 654 : for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
1775 : : {
1776 : 255 : const char *prop = omp_context_name_list_prop (p);
1777 : 255 : if (prop == NULL)
1778 : : return 0;
1779 : 254 : if (!strcmp (prop, "any"))
1780 : 24 : continue;
1781 : 230 : if (!strcmp (prop, "host"))
1782 : : {
1783 : : #ifdef ACCEL_COMPILER
1784 : : return 0;
1785 : : #else
1786 : 61 : if (omp_maybe_offloaded ())
1787 : : ret = -1;
1788 : 61 : continue;
1789 : : #endif
1790 : : }
1791 : 169 : if (!strcmp (prop, "nohost"))
1792 : : {
1793 : : #ifndef ACCEL_COMPILER
1794 : : if (omp_maybe_offloaded ())
1795 : : ret = -1;
1796 : : else
1797 : : return 0;
1798 : : #endif
1799 : : continue;
1800 : : }
1801 : 153 : int r = 0;
1802 : 153 : if (targetm.omp.device_kind_arch_isa != NULL)
1803 : 153 : r = targetm.omp.device_kind_arch_isa (omp_device_kind,
1804 : : prop);
1805 : : else
1806 : 0 : r = strcmp (prop, "cpu") == 0;
1807 : 153 : if (r == 0 || (r == -1 && symtab->state != PARSING))
1808 : : {
1809 : : /* If we are or might be in a target region or
1810 : : declare target function, need to take into account
1811 : : also offloading values. */
1812 : : if (!omp_maybe_offloaded ())
1813 : : return 0;
1814 : : if (ENABLE_OFFLOADING)
1815 : : {
1816 : : const char *kinds = omp_offload_device_kind;
1817 : : if (omp_offload_device_kind_arch_isa (kinds, prop))
1818 : : {
1819 : : ret = -1;
1820 : : continue;
1821 : : }
1822 : : }
1823 : : return 0;
1824 : : }
1825 : : else if (r == -1)
1826 : : ret = -1;
1827 : : /* If kind matches on the host, it still might not match
1828 : : in the offloading region. */
1829 : : else if (omp_maybe_offloaded ())
1830 : : ret = -1;
1831 : : }
1832 : : break;
1833 : 368 : case OMP_TRAIT_DEVICE_ISA:
1834 : 368 : if (set == OMP_TRAIT_SET_DEVICE)
1835 : 1176 : for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
1836 : : {
1837 : 558 : const char *isa = omp_context_name_list_prop (p);
1838 : 558 : if (isa == NULL)
1839 : : return 0;
1840 : 558 : int r = 0;
1841 : 558 : if (targetm.omp.device_kind_arch_isa != NULL)
1842 : 558 : r = targetm.omp.device_kind_arch_isa (omp_device_isa,
1843 : : isa);
1844 : 558 : if (r == 0 || (r == -1 && symtab->state != PARSING))
1845 : : {
1846 : : /* If isa is valid on the target, but not in the
1847 : : current function and current function has
1848 : : #pragma omp declare simd on it, some simd clones
1849 : : might have the isa added later on. */
1850 : 110 : if (r == -1
1851 : 110 : && targetm.simd_clone.compute_vecsize_and_simdlen
1852 : 110 : && (cfun == NULL || !cfun->after_inlining))
1853 : : {
1854 : 26 : tree attrs
1855 : 26 : = DECL_ATTRIBUTES (current_function_decl);
1856 : 26 : if (lookup_attribute ("omp declare simd", attrs))
1857 : : {
1858 : 17 : ret = -1;
1859 : 17 : continue;
1860 : : }
1861 : : }
1862 : : /* If we are or might be in a target region or
1863 : : declare target function, need to take into account
1864 : : also offloading values. */
1865 : 118 : if (!omp_maybe_offloaded ())
1866 : 118 : return 0;
1867 : : if (ENABLE_OFFLOADING)
1868 : : {
1869 : : const char *isas = omp_offload_device_isa;
1870 : : if (omp_offload_device_kind_arch_isa (isas, isa))
1871 : : {
1872 : : ret = -1;
1873 : : continue;
1874 : : }
1875 : : }
1876 : : return 0;
1877 : : }
1878 : : else if (r == -1)
1879 : : ret = -1;
1880 : : /* If isa matches on the host, it still might not match
1881 : : in the offloading region. */
1882 : : else if (omp_maybe_offloaded ())
1883 : : ret = -1;
1884 : : }
1885 : : break;
1886 : 409 : case OMP_TRAIT_USER_CONDITION:
1887 : 409 : if (set == OMP_TRAIT_SET_USER)
1888 : 827 : for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
1889 : 406 : if (OMP_TP_NAME (p) == NULL_TREE)
1890 : : {
1891 : 406 : if (integer_zerop (OMP_TP_VALUE (p)))
1892 : : return 0;
1893 : 279 : if (integer_nonzerop (OMP_TP_VALUE (p)))
1894 : : break;
1895 : : ret = -1;
1896 : : }
1897 : : break;
1898 : : default:
1899 : : break;
1900 : : }
1901 : : }
1902 : : }
1903 : : return ret;
1904 : : }
1905 : :
1906 : : /* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
1907 : : in omp_context_selector_set_compare. */
1908 : :
1909 : : static int
1910 : 18 : omp_construct_simd_compare (tree clauses1, tree clauses2)
1911 : : {
1912 : 18 : if (clauses1 == NULL_TREE)
1913 : 0 : return clauses2 == NULL_TREE ? 0 : -1;
1914 : 18 : if (clauses2 == NULL_TREE)
1915 : : return 1;
1916 : :
1917 : 54 : int r = 0;
1918 : 36 : struct declare_variant_simd_data {
1919 : : bool inbranch, notinbranch;
1920 : : tree simdlen;
1921 : : auto_vec<tree,16> data_sharing;
1922 : : auto_vec<tree,16> aligned;
1923 : 36 : declare_variant_simd_data ()
1924 : 36 : : inbranch(false), notinbranch(false), simdlen(NULL_TREE) {}
1925 : 126 : } data[2];
1926 : : unsigned int i;
1927 : 54 : for (i = 0; i < 2; i++)
1928 : 196 : for (tree c = i ? clauses2 : clauses1; c; c = OMP_CLAUSE_CHAIN (c))
1929 : : {
1930 : 124 : vec<tree> *v;
1931 : 124 : switch (OMP_CLAUSE_CODE (c))
1932 : : {
1933 : 12 : case OMP_CLAUSE_INBRANCH:
1934 : 12 : data[i].inbranch = true;
1935 : 12 : continue;
1936 : 24 : case OMP_CLAUSE_NOTINBRANCH:
1937 : 24 : data[i].notinbranch = true;
1938 : 24 : continue;
1939 : 36 : case OMP_CLAUSE_SIMDLEN:
1940 : 36 : data[i].simdlen = OMP_CLAUSE_SIMDLEN_EXPR (c);
1941 : 36 : continue;
1942 : 36 : case OMP_CLAUSE_UNIFORM:
1943 : 36 : case OMP_CLAUSE_LINEAR:
1944 : 36 : v = &data[i].data_sharing;
1945 : 36 : break;
1946 : 16 : case OMP_CLAUSE_ALIGNED:
1947 : 16 : v = &data[i].aligned;
1948 : 16 : break;
1949 : 0 : default:
1950 : 0 : gcc_unreachable ();
1951 : : }
1952 : 52 : unsigned HOST_WIDE_INT argno = tree_to_uhwi (OMP_CLAUSE_DECL (c));
1953 : 104 : if (argno >= v->length ())
1954 : 52 : v->safe_grow_cleared (argno + 1, true);
1955 : 52 : (*v)[argno] = c;
1956 : : }
1957 : : /* Here, r is used as a bitmask, 2 is set if CLAUSES1 has something
1958 : : CLAUSES2 doesn't, 1 is set if CLAUSES2 has something CLAUSES1
1959 : : doesn't. Thus, r == 3 implies return value 2, r == 1 implies
1960 : : -1, r == 2 implies 1 and r == 0 implies 0. */
1961 : 18 : if (data[0].inbranch != data[1].inbranch)
1962 : 0 : r |= data[0].inbranch ? 2 : 1;
1963 : 18 : if (data[0].notinbranch != data[1].notinbranch)
1964 : 0 : r |= data[0].notinbranch ? 2 : 1;
1965 : 18 : if (!simple_cst_equal (data[0].simdlen, data[1].simdlen))
1966 : : {
1967 : 0 : if (data[0].simdlen && data[1].simdlen)
1968 : : return 2;
1969 : 0 : r |= data[0].simdlen ? 2 : 1;
1970 : : }
1971 : 54 : if (data[0].data_sharing.length () < data[1].data_sharing.length ()
1972 : 36 : || data[0].aligned.length () < data[1].aligned.length ())
1973 : 0 : r |= 1;
1974 : : tree c1, c2;
1975 : 58 : FOR_EACH_VEC_ELT (data[0].data_sharing, i, c1)
1976 : : {
1977 : 48 : c2 = (i < data[1].data_sharing.length ()
1978 : 96 : ? data[1].data_sharing[i] : NULL_TREE);
1979 : 48 : if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
1980 : : {
1981 : 0 : r |= c1 != NULL_TREE ? 2 : 1;
1982 : 0 : continue;
1983 : : }
1984 : 48 : if (c1 == NULL_TREE)
1985 : 30 : continue;
1986 : 18 : if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_CODE (c2))
1987 : : return 2;
1988 : 13 : if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_LINEAR)
1989 : 7 : continue;
1990 : 6 : if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1)
1991 : 6 : != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2))
1992 : : return 2;
1993 : 6 : if (OMP_CLAUSE_LINEAR_KIND (c1) != OMP_CLAUSE_LINEAR_KIND (c2))
1994 : : return 2;
1995 : 6 : if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1),
1996 : 6 : OMP_CLAUSE_LINEAR_STEP (c2)))
1997 : : return 2;
1998 : : }
1999 : 23 : FOR_EACH_VEC_ELT (data[0].aligned, i, c1)
2000 : : {
2001 : 36 : c2 = i < data[1].aligned.length () ? data[1].aligned[i] : NULL_TREE;
2002 : 18 : if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
2003 : : {
2004 : 0 : r |= c1 != NULL_TREE ? 2 : 1;
2005 : 0 : continue;
2006 : : }
2007 : 18 : if (c1 == NULL_TREE)
2008 : 12 : continue;
2009 : 6 : if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1),
2010 : 6 : OMP_CLAUSE_ALIGNED_ALIGNMENT (c2)))
2011 : : return 2;
2012 : : }
2013 : 5 : switch (r)
2014 : : {
2015 : : case 0: return 0;
2016 : 0 : case 1: return -1;
2017 : 0 : case 2: return 1;
2018 : : case 3: return 2;
2019 : 0 : default: gcc_unreachable ();
2020 : : }
2021 : 54 : }
2022 : :
2023 : : /* Compare properties of selectors SEL from SET other than construct.
2024 : : CTX1 and CTX2 are the lists of properties to compare.
2025 : : Return 0/-1/1/2 as in omp_context_selector_set_compare.
2026 : : Unlike set names or selector names, properties can have duplicates. */
2027 : :
2028 : : static int
2029 : 55 : omp_context_selector_props_compare (enum omp_tss_code set,
2030 : : enum omp_ts_code sel,
2031 : : tree ctx1, tree ctx2)
2032 : : {
2033 : 55 : int ret = 0;
2034 : 160 : for (int pass = 0; pass < 2; pass++)
2035 : 330 : for (tree p1 = pass ? ctx2 : ctx1; p1; p1 = TREE_CHAIN (p1))
2036 : : {
2037 : 120 : tree p2;
2038 : 310 : for (p2 = pass ? ctx1 : ctx2; p2; p2 = TREE_CHAIN (p2))
2039 : 180 : if (OMP_TP_NAME (p1) == OMP_TP_NAME (p2))
2040 : : {
2041 : 180 : if (OMP_TP_NAME (p1) == NULL_TREE)
2042 : : {
2043 : 40 : if (set == OMP_TRAIT_SET_USER
2044 : 40 : && sel == OMP_TRAIT_USER_CONDITION)
2045 : : {
2046 : 80 : if (integer_zerop (OMP_TP_VALUE (p1))
2047 : 40 : != integer_zerop (OMP_TP_VALUE (p2)))
2048 : : return 2;
2049 : : break;
2050 : : }
2051 : 0 : if (simple_cst_equal (OMP_TP_VALUE (p1), OMP_TP_VALUE (p2)))
2052 : : break;
2053 : : }
2054 : 140 : else if (OMP_TP_NAME (p1) == OMP_TP_NAMELIST_NODE)
2055 : : {
2056 : : /* Handle string constant vs identifier comparison for
2057 : : name-list properties. */
2058 : 140 : const char *n1 = omp_context_name_list_prop (p1);
2059 : 140 : const char *n2 = omp_context_name_list_prop (p2);
2060 : 140 : if (n1 && n2 && !strcmp (n1, n2))
2061 : : break;
2062 : : }
2063 : : else
2064 : : break;
2065 : : }
2066 : 10 : if (p2 == NULL_TREE)
2067 : : {
2068 : 10 : int r = pass ? -1 : 1;
2069 : 10 : if (ret && ret != r)
2070 : : return 2;
2071 : 10 : else if (pass)
2072 : 5 : return r;
2073 : : else
2074 : : {
2075 : : ret = r;
2076 : : break;
2077 : : }
2078 : : }
2079 : : }
2080 : : return ret;
2081 : : }
2082 : :
2083 : : /* Compare single context selector sets CTX1 and CTX2 with SET name.
2084 : : CTX1 and CTX2 are lists of trait-selectors.
2085 : : Return 0 if CTX1 is equal to CTX2,
2086 : : -1 if CTX1 is a strict subset of CTX2,
2087 : : 1 if CTX2 is a strict subset of CTX1, or
2088 : : 2 if neither context is a subset of another one. */
2089 : :
2090 : : int
2091 : 333 : omp_context_selector_set_compare (enum omp_tss_code set, tree ctx1, tree ctx2)
2092 : : {
2093 : :
2094 : : /* If either list includes an ignored selector trait, neither can
2095 : : be a subset of the other. */
2096 : 777 : for (tree ts = ctx1; ts; ts = TREE_CHAIN (ts))
2097 : 444 : if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
2098 : : return 2;
2099 : 795 : for (tree ts = ctx2; ts; ts = TREE_CHAIN (ts))
2100 : 462 : if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
2101 : : return 2;
2102 : :
2103 : 333 : bool swapped = false;
2104 : 333 : int ret = 0;
2105 : 333 : int len1 = list_length (ctx1);
2106 : 333 : int len2 = list_length (ctx2);
2107 : 333 : int cnt = 0;
2108 : 333 : if (len1 < len2)
2109 : : {
2110 : 43 : swapped = true;
2111 : 43 : std::swap (ctx1, ctx2);
2112 : 43 : std::swap (len1, len2);
2113 : : }
2114 : :
2115 : 333 : if (set == OMP_TRAIT_SET_CONSTRUCT)
2116 : : {
2117 : : tree ts1;
2118 : : tree ts2 = ctx2;
2119 : : /* Handle construct set specially. In this case the order
2120 : : of the selector matters too. */
2121 : 228 : for (ts1 = ctx1; ts1; ts1 = TREE_CHAIN (ts1))
2122 : 223 : if (OMP_TS_CODE (ts1) == OMP_TS_CODE (ts2))
2123 : : {
2124 : 163 : int r = 0;
2125 : 163 : if (OMP_TS_CODE (ts1) == OMP_TRAIT_CONSTRUCT_SIMD)
2126 : 18 : r = omp_construct_simd_compare (OMP_TS_PROPERTIES (ts1),
2127 : 18 : OMP_TS_PROPERTIES (ts2));
2128 : 163 : if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
2129 : 13 : return 2;
2130 : 150 : if (ret == 0)
2131 : 91 : ret = r;
2132 : 150 : ts2 = TREE_CHAIN (ts2);
2133 : 150 : if (ts2 == NULL_TREE)
2134 : : {
2135 : 84 : ts1 = TREE_CHAIN (ts1);
2136 : 84 : break;
2137 : : }
2138 : : }
2139 : 60 : else if (ret < 0)
2140 : : return 2;
2141 : : else
2142 : : ret = 1;
2143 : 89 : if (ts2 != NULL_TREE)
2144 : : return 2;
2145 : 84 : if (ts1 != NULL_TREE)
2146 : : {
2147 : 28 : if (ret < 0)
2148 : : return 2;
2149 : : ret = 1;
2150 : : }
2151 : 56 : if (ret == 0)
2152 : : return 0;
2153 : 64 : return swapped ? -ret : ret;
2154 : : }
2155 : 359 : for (tree ts1 = ctx1; ts1; ts1 = TREE_CHAIN (ts1))
2156 : : {
2157 : 251 : enum omp_ts_code sel = OMP_TS_CODE (ts1);
2158 : 251 : tree ts2;
2159 : 334 : for (ts2 = ctx2; ts2; ts2 = TREE_CHAIN (ts2))
2160 : 261 : if (sel == OMP_TS_CODE (ts2))
2161 : : {
2162 : 178 : tree score1 = OMP_TS_SCORE (ts1);
2163 : 178 : tree score2 = OMP_TS_SCORE (ts2);
2164 : 178 : if (score1 && score2 && !simple_cst_equal (score1, score2))
2165 : : return 2;
2166 : :
2167 : 119 : int r = omp_context_selector_props_compare (set, OMP_TS_CODE (ts1),
2168 : 55 : OMP_TS_PROPERTIES (ts1),
2169 : 55 : OMP_TS_PROPERTIES (ts2));
2170 : 55 : if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
2171 : : return 2;
2172 : 55 : if (ret == 0)
2173 : 50 : ret = r;
2174 : 55 : cnt++;
2175 : 55 : break;
2176 : : }
2177 : 128 : if (ts2 == NULL_TREE)
2178 : : {
2179 : 73 : if (ret == -1)
2180 : : return 2;
2181 : : ret = 1;
2182 : : }
2183 : : }
2184 : 108 : if (cnt < len2)
2185 : : return 2;
2186 : 50 : if (ret == 0)
2187 : : return 0;
2188 : 20 : return swapped ? -ret : ret;
2189 : : }
2190 : :
2191 : : /* Compare whole context selector specification CTX1 and CTX2.
2192 : : Return 0 if CTX1 is equal to CTX2,
2193 : : -1 if CTX1 is a strict subset of CTX2,
2194 : : 1 if CTX2 is a strict subset of CTX1, or
2195 : : 2 if neither context is a subset of another one. */
2196 : :
2197 : : static int
2198 : 396 : omp_context_selector_compare (tree ctx1, tree ctx2)
2199 : : {
2200 : 396 : bool swapped = false;
2201 : 396 : int ret = 0;
2202 : 396 : int len1 = list_length (ctx1);
2203 : 396 : int len2 = list_length (ctx2);
2204 : 396 : int cnt = 0;
2205 : 396 : if (len1 < len2)
2206 : : {
2207 : 60 : swapped = true;
2208 : 60 : std::swap (ctx1, ctx2);
2209 : 60 : std::swap (len1, len2);
2210 : : }
2211 : 714 : for (tree tss1 = ctx1; tss1; tss1 = TREE_CHAIN (tss1))
2212 : : {
2213 : 514 : enum omp_tss_code set = OMP_TSS_CODE (tss1);
2214 : 514 : tree tss2;
2215 : 759 : for (tss2 = ctx2; tss2; tss2 = TREE_CHAIN (tss2))
2216 : 524 : if (set == OMP_TSS_CODE (tss2))
2217 : : {
2218 : 279 : int r
2219 : : = omp_context_selector_set_compare
2220 : 558 : (set, OMP_TSS_TRAIT_SELECTORS (tss1),
2221 : 279 : OMP_TSS_TRAIT_SELECTORS (tss2));
2222 : 279 : if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
2223 : : return 2;
2224 : 98 : if (ret == 0)
2225 : 93 : ret = r;
2226 : 98 : cnt++;
2227 : 98 : break;
2228 : : }
2229 : 333 : if (tss2 == NULL_TREE)
2230 : : {
2231 : 235 : if (ret == -1)
2232 : : return 2;
2233 : : ret = 1;
2234 : : }
2235 : : }
2236 : 200 : if (cnt < len2)
2237 : : return 2;
2238 : 78 : if (ret == 0)
2239 : : return 0;
2240 : 63 : return swapped ? -ret : ret;
2241 : : }
2242 : :
2243 : : /* From context selector CTX, return trait-selector with name SEL in
2244 : : trait-selector-set with name SET if any, or NULL_TREE if not found. */
2245 : : tree
2246 : 2222 : omp_get_context_selector (tree ctx, enum omp_tss_code set,
2247 : : enum omp_ts_code sel)
2248 : : {
2249 : 4697 : for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
2250 : 2685 : if (OMP_TSS_CODE (tss) == set)
2251 : 1736 : for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
2252 : 1135 : if (OMP_TS_CODE (ts) == sel)
2253 : 210 : return ts;
2254 : : return NULL_TREE;
2255 : : }
2256 : :
2257 : : /* Similar, but returns the whole trait-selector list for SET in CTX. */
2258 : : tree
2259 : 1542 : omp_get_context_selector_list (tree ctx, enum omp_tss_code set)
2260 : : {
2261 : 2802 : for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
2262 : 1707 : if (OMP_TSS_CODE (tss) == set)
2263 : 447 : return OMP_TSS_TRAIT_SELECTORS (tss);
2264 : : return NULL_TREE;
2265 : : }
2266 : :
2267 : : /* Map string S onto a trait selector set code. */
2268 : : enum omp_tss_code
2269 : 1971 : omp_lookup_tss_code (const char * s)
2270 : : {
2271 : 5808 : for (int i = 0; i < OMP_TRAIT_SET_LAST; i++)
2272 : 5785 : if (strcmp (s, omp_tss_map[i]) == 0)
2273 : 1948 : return (enum omp_tss_code) i;
2274 : : return OMP_TRAIT_SET_INVALID;
2275 : : }
2276 : :
2277 : : /* Map string S onto a trait selector code for set SET. */
2278 : : enum omp_ts_code
2279 : 2398 : omp_lookup_ts_code (enum omp_tss_code set, const char *s)
2280 : : {
2281 : 2398 : unsigned int mask = 1 << set;
2282 : 25408 : for (int i = 0; i < OMP_TRAIT_LAST; i++)
2283 : 25319 : if ((mask & omp_ts_map[i].tss_mask) != 0
2284 : 5692 : && strcmp (s, omp_ts_map[i].name) == 0)
2285 : 2309 : return (enum omp_ts_code) i;
2286 : : return OMP_TRAIT_INVALID;
2287 : : }
2288 : :
2289 : : /* Needs to be a GC-friendly widest_int variant, but precision is
2290 : : desirable to be the same on all targets. */
2291 : : typedef generic_wide_int <fixed_wide_int_storage <1024> > score_wide_int;
2292 : :
2293 : : /* Compute *SCORE for context selector CTX. Return true if the score
2294 : : would be different depending on whether it is a declare simd clone or
2295 : : not. DECLARE_SIMD should be true for the case when it would be
2296 : : a declare simd clone. */
2297 : :
2298 : : static bool
2299 : 257 : omp_context_compute_score (tree ctx, score_wide_int *score, bool declare_simd)
2300 : : {
2301 : 257 : tree selectors
2302 : 257 : = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT);
2303 : 257 : bool has_kind = omp_get_context_selector (ctx, OMP_TRAIT_SET_DEVICE,
2304 : 257 : OMP_TRAIT_DEVICE_KIND);
2305 : 257 : bool has_arch = omp_get_context_selector (ctx, OMP_TRAIT_SET_DEVICE,
2306 : 257 : OMP_TRAIT_DEVICE_ARCH);
2307 : 257 : bool has_isa = omp_get_context_selector (ctx, OMP_TRAIT_SET_DEVICE,
2308 : 257 : OMP_TRAIT_DEVICE_ISA);
2309 : 257 : bool ret = false;
2310 : 257 : *score = 1;
2311 : 602 : for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
2312 : 345 : if (OMP_TSS_TRAIT_SELECTORS (tss) != selectors)
2313 : 580 : for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
2314 : : {
2315 : 443 : tree s = OMP_TS_SCORE (ts);
2316 : 153 : if (s && TREE_CODE (s) == INTEGER_CST)
2317 : 306 : *score += score_wide_int::from (wi::to_wide (s),
2318 : 306 : TYPE_SIGN (TREE_TYPE (s)));
2319 : : }
2320 : :
2321 : 257 : if (selectors || has_kind || has_arch || has_isa)
2322 : : {
2323 : 177 : int nconstructs = list_length (selectors);
2324 : 177 : enum tree_code *constructs = NULL;
2325 : 177 : if (nconstructs)
2326 : : {
2327 : 55 : constructs
2328 : 55 : = (enum tree_code *) alloca (nconstructs
2329 : : * sizeof (enum tree_code));
2330 : 55 : omp_construct_traits_to_codes (selectors, nconstructs, constructs);
2331 : : }
2332 : 177 : int *scores
2333 : 177 : = (int *) alloca ((2 * nconstructs + 2) * sizeof (int));
2334 : 177 : if (omp_construct_selector_matches (constructs, nconstructs, scores)
2335 : : == 2)
2336 : 102 : ret = true;
2337 : 177 : int b = declare_simd ? nconstructs + 1 : 0;
2338 : 177 : if (scores[b + nconstructs] + 4U < score->get_precision ())
2339 : : {
2340 : 286 : for (int n = 0; n < nconstructs; ++n)
2341 : : {
2342 : 109 : if (scores[b + n] < 0)
2343 : : {
2344 : 0 : *score = -1;
2345 : 0 : return ret;
2346 : : }
2347 : 109 : *score += wi::shifted_mask <score_wide_int> (scores[b + n], 1, false);
2348 : : }
2349 : 177 : if (has_kind)
2350 : 136 : *score += wi::shifted_mask <score_wide_int> (scores[b + nconstructs],
2351 : 68 : 1, false);
2352 : 177 : if (has_arch)
2353 : 10 : *score += wi::shifted_mask <score_wide_int> (scores[b + nconstructs] + 1,
2354 : 5 : 1, false);
2355 : 177 : if (has_isa)
2356 : 98 : *score += wi::shifted_mask <score_wide_int> (scores[b + nconstructs] + 2,
2357 : 49 : 1, false);
2358 : : }
2359 : : else /* FIXME: Implement this. */
2360 : 0 : gcc_unreachable ();
2361 : : }
2362 : : return ret;
2363 : : }
2364 : :
2365 : : /* Class describing a single variant. */
2366 : 82 : struct GTY(()) omp_declare_variant_entry {
2367 : : /* NODE of the variant. */
2368 : : cgraph_node *variant;
2369 : : /* Score if not in declare simd clone. */
2370 : : score_wide_int score;
2371 : : /* Score if in declare simd clone. */
2372 : : score_wide_int score_in_declare_simd_clone;
2373 : : /* Context selector for the variant. */
2374 : : tree ctx;
2375 : : /* True if the context selector is known to match already. */
2376 : : bool matches;
2377 : : };
2378 : :
2379 : : /* Class describing a function with variants. */
2380 : : struct GTY((for_user)) omp_declare_variant_base_entry {
2381 : : /* NODE of the base function. */
2382 : : cgraph_node *base;
2383 : : /* NODE of the artificial function created for the deferred variant
2384 : : resolution. */
2385 : : cgraph_node *node;
2386 : : /* Vector of the variants. */
2387 : : vec<omp_declare_variant_entry, va_gc> *variants;
2388 : : };
2389 : :
2390 : : struct omp_declare_variant_hasher
2391 : : : ggc_ptr_hash<omp_declare_variant_base_entry> {
2392 : : static hashval_t hash (omp_declare_variant_base_entry *);
2393 : : static bool equal (omp_declare_variant_base_entry *,
2394 : : omp_declare_variant_base_entry *);
2395 : : };
2396 : :
2397 : : hashval_t
2398 : 24 : omp_declare_variant_hasher::hash (omp_declare_variant_base_entry *x)
2399 : : {
2400 : 24 : inchash::hash hstate;
2401 : 24 : hstate.add_int (DECL_UID (x->base->decl));
2402 : 24 : hstate.add_int (x->variants->length ());
2403 : 24 : omp_declare_variant_entry *variant;
2404 : 24 : unsigned int i;
2405 : 80 : FOR_EACH_VEC_SAFE_ELT (x->variants, i, variant)
2406 : : {
2407 : 56 : hstate.add_int (DECL_UID (variant->variant->decl));
2408 : 56 : hstate.add_wide_int (variant->score);
2409 : 56 : hstate.add_wide_int (variant->score_in_declare_simd_clone);
2410 : 56 : hstate.add_ptr (variant->ctx);
2411 : 56 : hstate.add_int (variant->matches);
2412 : : }
2413 : 24 : return hstate.end ();
2414 : : }
2415 : :
2416 : : bool
2417 : 10 : omp_declare_variant_hasher::equal (omp_declare_variant_base_entry *x,
2418 : : omp_declare_variant_base_entry *y)
2419 : : {
2420 : 10 : if (x->base != y->base
2421 : 10 : || x->variants->length () != y->variants->length ())
2422 : : return false;
2423 : : omp_declare_variant_entry *variant;
2424 : : unsigned int i;
2425 : 36 : FOR_EACH_VEC_SAFE_ELT (x->variants, i, variant)
2426 : 26 : if (variant->variant != (*y->variants)[i].variant
2427 : 26 : || variant->score != (*y->variants)[i].score
2428 : 52 : || (variant->score_in_declare_simd_clone
2429 : 26 : != (*y->variants)[i].score_in_declare_simd_clone)
2430 : 26 : || variant->ctx != (*y->variants)[i].ctx
2431 : 52 : || variant->matches != (*y->variants)[i].matches)
2432 : : return false;
2433 : : return true;
2434 : : }
2435 : :
2436 : : static GTY(()) hash_table<omp_declare_variant_hasher> *omp_declare_variants;
2437 : :
2438 : : struct omp_declare_variant_alt_hasher
2439 : : : ggc_ptr_hash<omp_declare_variant_base_entry> {
2440 : : static hashval_t hash (omp_declare_variant_base_entry *);
2441 : : static bool equal (omp_declare_variant_base_entry *,
2442 : : omp_declare_variant_base_entry *);
2443 : : };
2444 : :
2445 : : hashval_t
2446 : 0 : omp_declare_variant_alt_hasher::hash (omp_declare_variant_base_entry *x)
2447 : : {
2448 : 0 : return DECL_UID (x->node->decl);
2449 : : }
2450 : :
2451 : : bool
2452 : 121 : omp_declare_variant_alt_hasher::equal (omp_declare_variant_base_entry *x,
2453 : : omp_declare_variant_base_entry *y)
2454 : : {
2455 : 121 : return x->node == y->node;
2456 : : }
2457 : :
2458 : : static GTY(()) hash_table<omp_declare_variant_alt_hasher>
2459 : : *omp_declare_variant_alt;
2460 : :
2461 : : /* Try to resolve declare variant after gimplification. */
2462 : :
2463 : : static tree
2464 : 145 : omp_resolve_late_declare_variant (tree alt)
2465 : : {
2466 : 145 : cgraph_node *node = cgraph_node::get (alt);
2467 : 145 : cgraph_node *cur_node = cgraph_node::get (cfun->decl);
2468 : 145 : if (node == NULL
2469 : 145 : || !node->declare_variant_alt
2470 : 117 : || !cfun->after_inlining)
2471 : : return alt;
2472 : :
2473 : 117 : omp_declare_variant_base_entry entry;
2474 : 117 : entry.base = NULL;
2475 : 117 : entry.node = node;
2476 : 117 : entry.variants = NULL;
2477 : 117 : omp_declare_variant_base_entry *entryp
2478 : 117 : = omp_declare_variant_alt->find_with_hash (&entry, DECL_UID (alt));
2479 : :
2480 : 117 : unsigned int i, j;
2481 : 117 : omp_declare_variant_entry *varentry1, *varentry2;
2482 : 117 : auto_vec <bool, 16> matches;
2483 : 117 : unsigned int nmatches = 0;
2484 : 441 : FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2485 : : {
2486 : 333 : if (varentry1->matches)
2487 : : {
2488 : : /* This has been checked to be ok already. */
2489 : 216 : matches.safe_push (true);
2490 : 216 : nmatches++;
2491 : 216 : continue;
2492 : : }
2493 : 117 : switch (omp_context_selector_matches (varentry1->ctx))
2494 : : {
2495 : 84 : case 0:
2496 : 84 : matches.safe_push (false);
2497 : 84 : break;
2498 : : case -1:
2499 : : return alt;
2500 : 24 : default:
2501 : 24 : matches.safe_push (true);
2502 : 24 : nmatches++;
2503 : 24 : break;
2504 : : }
2505 : : }
2506 : :
2507 : 108 : if (nmatches == 0)
2508 : 0 : return entryp->base->decl;
2509 : :
2510 : : /* A context selector that is a strict subset of another context selector
2511 : : has a score of zero. */
2512 : 432 : FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2513 : 324 : if (matches[i])
2514 : : {
2515 : 480 : for (j = i + 1;
2516 : 804 : vec_safe_iterate (entryp->variants, j, &varentry2); ++j)
2517 : 240 : if (matches[j])
2518 : : {
2519 : 156 : int r = omp_context_selector_compare (varentry1->ctx,
2520 : : varentry2->ctx);
2521 : 156 : if (r == -1)
2522 : : {
2523 : : /* ctx1 is a strict subset of ctx2, ignore ctx1. */
2524 : 0 : matches[i] = false;
2525 : 0 : break;
2526 : : }
2527 : 156 : else if (r == 1)
2528 : : /* ctx2 is a strict subset of ctx1, remove ctx2. */
2529 : 0 : matches[j] = false;
2530 : : }
2531 : : }
2532 : :
2533 : 108 : score_wide_int max_score = -1;
2534 : 108 : varentry2 = NULL;
2535 : 432 : FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2536 : 324 : if (matches[i])
2537 : : {
2538 : 480 : score_wide_int score
2539 : 240 : = (cur_node->simdclone ? varentry1->score_in_declare_simd_clone
2540 : : : varentry1->score);
2541 : 240 : if (score > max_score)
2542 : : {
2543 : 162 : max_score = score;
2544 : 162 : varentry2 = varentry1;
2545 : : }
2546 : : }
2547 : 108 : return varentry2->variant->decl;
2548 : 117 : }
2549 : :
2550 : : /* Hook to adjust hash tables on cgraph_node removal. */
2551 : :
2552 : : static void
2553 : 15 : omp_declare_variant_remove_hook (struct cgraph_node *node, void *)
2554 : : {
2555 : 15 : if (!node->declare_variant_alt)
2556 : : return;
2557 : :
2558 : : /* Drop this hash table completely. */
2559 : 2 : omp_declare_variants = NULL;
2560 : : /* And remove node from the other hash table. */
2561 : 2 : if (omp_declare_variant_alt)
2562 : : {
2563 : 2 : omp_declare_variant_base_entry entry;
2564 : 2 : entry.base = NULL;
2565 : 2 : entry.node = node;
2566 : 2 : entry.variants = NULL;
2567 : 2 : omp_declare_variant_alt->remove_elt_with_hash (&entry,
2568 : 2 : DECL_UID (node->decl));
2569 : : }
2570 : : }
2571 : :
2572 : : /* Try to resolve declare variant, return the variant decl if it should
2573 : : be used instead of base, or base otherwise. */
2574 : :
2575 : : tree
2576 : 194845 : omp_resolve_declare_variant (tree base)
2577 : : {
2578 : 194845 : tree variant1 = NULL_TREE, variant2 = NULL_TREE;
2579 : 194845 : if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
2580 : 145 : return omp_resolve_late_declare_variant (base);
2581 : :
2582 : 194700 : auto_vec <tree, 16> variants;
2583 : 194700 : auto_vec <bool, 16> defer;
2584 : 194700 : bool any_deferred = false;
2585 : 195249 : for (tree attr = DECL_ATTRIBUTES (base); attr; attr = TREE_CHAIN (attr))
2586 : : {
2587 : 99021 : attr = lookup_attribute ("omp declare variant base", attr);
2588 : 99021 : if (attr == NULL_TREE)
2589 : : break;
2590 : 585 : if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr))) != FUNCTION_DECL)
2591 : 0 : continue;
2592 : 585 : cgraph_node *node = cgraph_node::get (base);
2593 : : /* If this is already a magic decl created by this function,
2594 : : don't process it again. */
2595 : 585 : if (node && node->declare_variant_alt)
2596 : 36 : return base;
2597 : 549 : switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr))))
2598 : : {
2599 : : case 0:
2600 : : /* No match, ignore. */
2601 : : break;
2602 : 37 : case -1:
2603 : : /* Needs to be deferred. */
2604 : 37 : any_deferred = true;
2605 : 37 : variants.safe_push (attr);
2606 : 37 : defer.safe_push (true);
2607 : 37 : break;
2608 : 384 : default:
2609 : 384 : variants.safe_push (attr);
2610 : 384 : defer.safe_push (false);
2611 : 384 : break;
2612 : : }
2613 : : }
2614 : 194700 : if (variants.length () == 0)
2615 : : return base;
2616 : :
2617 : 221 : if (any_deferred)
2618 : : {
2619 : 29 : score_wide_int max_score1 = 0;
2620 : 29 : score_wide_int max_score2 = 0;
2621 : 29 : bool first = true;
2622 : 29 : unsigned int i;
2623 : 29 : tree attr1, attr2;
2624 : 29 : omp_declare_variant_base_entry entry;
2625 : 29 : entry.base = cgraph_node::get_create (base);
2626 : 29 : entry.node = NULL;
2627 : 58 : vec_alloc (entry.variants, variants.length ());
2628 : 105 : FOR_EACH_VEC_ELT (variants, i, attr1)
2629 : : {
2630 : 76 : score_wide_int score1;
2631 : 76 : score_wide_int score2;
2632 : 76 : bool need_two;
2633 : 76 : tree ctx = TREE_VALUE (TREE_VALUE (attr1));
2634 : 76 : need_two = omp_context_compute_score (ctx, &score1, false);
2635 : 76 : if (need_two)
2636 : 51 : omp_context_compute_score (ctx, &score2, true);
2637 : : else
2638 : 25 : score2 = score1;
2639 : 76 : if (first)
2640 : : {
2641 : 29 : first = false;
2642 : 29 : max_score1 = score1;
2643 : 29 : max_score2 = score2;
2644 : 29 : if (!defer[i])
2645 : : {
2646 : 8 : variant1 = attr1;
2647 : 8 : variant2 = attr1;
2648 : : }
2649 : : }
2650 : : else
2651 : : {
2652 : 47 : if (max_score1 == score1)
2653 : : variant1 = NULL_TREE;
2654 : 38 : else if (score1 > max_score1)
2655 : : {
2656 : 19 : max_score1 = score1;
2657 : 19 : variant1 = defer[i] ? NULL_TREE : attr1;
2658 : : }
2659 : 47 : if (max_score2 == score2)
2660 : : variant2 = NULL_TREE;
2661 : 47 : else if (score2 > max_score2)
2662 : : {
2663 : 19 : max_score2 = score2;
2664 : 19 : variant2 = defer[i] ? NULL_TREE : attr1;
2665 : : }
2666 : : }
2667 : 76 : omp_declare_variant_entry varentry;
2668 : 76 : varentry.variant
2669 : 76 : = cgraph_node::get_create (TREE_PURPOSE (TREE_VALUE (attr1)));
2670 : 76 : varentry.score = score1;
2671 : 76 : varentry.score_in_declare_simd_clone = score2;
2672 : 76 : varentry.ctx = ctx;
2673 : 76 : varentry.matches = !defer[i];
2674 : 76 : entry.variants->quick_push (varentry);
2675 : : }
2676 : :
2677 : : /* If there is a clear winner variant with the score which is not
2678 : : deferred, verify it is not a strict subset of any other context
2679 : : selector and if it is not, it is the best alternative no matter
2680 : : whether the others do or don't match. */
2681 : 29 : if (variant1 && variant1 == variant2)
2682 : : {
2683 : 5 : tree ctx1 = TREE_VALUE (TREE_VALUE (variant1));
2684 : 25 : FOR_EACH_VEC_ELT (variants, i, attr2)
2685 : : {
2686 : 20 : if (attr2 == variant1)
2687 : 5 : continue;
2688 : 15 : tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
2689 : 15 : int r = omp_context_selector_compare (ctx1, ctx2);
2690 : 15 : if (r == -1)
2691 : : {
2692 : : /* The winner is a strict subset of ctx2, can't
2693 : : decide now. */
2694 : : variant1 = NULL_TREE;
2695 : : break;
2696 : : }
2697 : : }
2698 : 5 : if (variant1)
2699 : : {
2700 : 5 : vec_free (entry.variants);
2701 : 5 : return TREE_PURPOSE (TREE_VALUE (variant1));
2702 : : }
2703 : : }
2704 : :
2705 : 24 : static struct cgraph_node_hook_list *node_removal_hook_holder;
2706 : 24 : if (!node_removal_hook_holder)
2707 : 10 : node_removal_hook_holder
2708 : 10 : = symtab->add_cgraph_removal_hook (omp_declare_variant_remove_hook,
2709 : : NULL);
2710 : :
2711 : 24 : if (omp_declare_variants == NULL)
2712 : 10 : omp_declare_variants
2713 : 10 : = hash_table<omp_declare_variant_hasher>::create_ggc (64);
2714 : 24 : omp_declare_variant_base_entry **slot
2715 : 24 : = omp_declare_variants->find_slot (&entry, INSERT);
2716 : 24 : if (*slot != NULL)
2717 : : {
2718 : 10 : vec_free (entry.variants);
2719 : 10 : return (*slot)->node->decl;
2720 : : }
2721 : :
2722 : 14 : *slot = ggc_cleared_alloc<omp_declare_variant_base_entry> ();
2723 : 14 : (*slot)->base = entry.base;
2724 : 14 : (*slot)->node = entry.base;
2725 : 14 : (*slot)->variants = entry.variants;
2726 : 14 : tree alt = build_decl (DECL_SOURCE_LOCATION (base), FUNCTION_DECL,
2727 : 14 : DECL_NAME (base), TREE_TYPE (base));
2728 : 14 : DECL_ARTIFICIAL (alt) = 1;
2729 : 14 : DECL_IGNORED_P (alt) = 1;
2730 : 14 : TREE_STATIC (alt) = 1;
2731 : 14 : tree attributes = DECL_ATTRIBUTES (base);
2732 : 14 : if (lookup_attribute ("noipa", attributes) == NULL)
2733 : : {
2734 : 14 : attributes = tree_cons (get_identifier ("noipa"), NULL, attributes);
2735 : 14 : if (lookup_attribute ("noinline", attributes) == NULL)
2736 : 14 : attributes = tree_cons (get_identifier ("noinline"), NULL,
2737 : : attributes);
2738 : 14 : if (lookup_attribute ("noclone", attributes) == NULL)
2739 : 14 : attributes = tree_cons (get_identifier ("noclone"), NULL,
2740 : : attributes);
2741 : 14 : if (lookup_attribute ("no_icf", attributes) == NULL)
2742 : 14 : attributes = tree_cons (get_identifier ("no_icf"), NULL,
2743 : : attributes);
2744 : : }
2745 : 14 : DECL_ATTRIBUTES (alt) = attributes;
2746 : 14 : DECL_INITIAL (alt) = error_mark_node;
2747 : 14 : (*slot)->node = cgraph_node::create (alt);
2748 : 14 : (*slot)->node->declare_variant_alt = 1;
2749 : 14 : (*slot)->node->create_reference (entry.base, IPA_REF_ADDR);
2750 : 14 : omp_declare_variant_entry *varentry;
2751 : 58 : FOR_EACH_VEC_SAFE_ELT (entry.variants, i, varentry)
2752 : 30 : (*slot)->node->create_reference (varentry->variant, IPA_REF_ADDR);
2753 : 14 : if (omp_declare_variant_alt == NULL)
2754 : 10 : omp_declare_variant_alt
2755 : 10 : = hash_table<omp_declare_variant_alt_hasher>::create_ggc (64);
2756 : 14 : *omp_declare_variant_alt->find_slot_with_hash (*slot, DECL_UID (alt),
2757 : 14 : INSERT) = *slot;
2758 : 14 : return alt;
2759 : : }
2760 : :
2761 : 192 : if (variants.length () == 1)
2762 : 114 : return TREE_PURPOSE (TREE_VALUE (variants[0]));
2763 : :
2764 : : /* A context selector that is a strict subset of another context selector
2765 : : has a score of zero. */
2766 : : tree attr1, attr2;
2767 : : unsigned int i, j;
2768 : 309 : FOR_EACH_VEC_ELT (variants, i, attr1)
2769 : 231 : if (attr1)
2770 : : {
2771 : 199 : tree ctx1 = TREE_VALUE (TREE_VALUE (attr1));
2772 : 624 : FOR_EACH_VEC_ELT_FROM (variants, j, attr2, i + 1)
2773 : 225 : if (attr2)
2774 : : {
2775 : 225 : tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
2776 : 225 : int r = omp_context_selector_compare (ctx1, ctx2);
2777 : 225 : if (r == -1)
2778 : : {
2779 : : /* ctx1 is a strict subset of ctx2, remove
2780 : : attr1 from the vector. */
2781 : 31 : variants[i] = NULL_TREE;
2782 : 31 : break;
2783 : : }
2784 : 194 : else if (r == 1)
2785 : : /* ctx2 is a strict subset of ctx1, remove attr2
2786 : : from the vector. */
2787 : 32 : variants[j] = NULL_TREE;
2788 : : }
2789 : : }
2790 : 78 : score_wide_int max_score1 = 0;
2791 : 78 : score_wide_int max_score2 = 0;
2792 : 78 : bool first = true;
2793 : 309 : FOR_EACH_VEC_ELT (variants, i, attr1)
2794 : 231 : if (attr1)
2795 : : {
2796 : 168 : if (variant1)
2797 : : {
2798 : 90 : score_wide_int score1;
2799 : 90 : score_wide_int score2;
2800 : 90 : bool need_two;
2801 : 90 : tree ctx;
2802 : 90 : if (first)
2803 : : {
2804 : 40 : first = false;
2805 : 40 : ctx = TREE_VALUE (TREE_VALUE (variant1));
2806 : 40 : need_two = omp_context_compute_score (ctx, &max_score1, false);
2807 : 40 : if (need_two)
2808 : 0 : omp_context_compute_score (ctx, &max_score2, true);
2809 : : else
2810 : 40 : max_score2 = max_score1;
2811 : : }
2812 : 90 : ctx = TREE_VALUE (TREE_VALUE (attr1));
2813 : 90 : need_two = omp_context_compute_score (ctx, &score1, false);
2814 : 90 : if (need_two)
2815 : 0 : omp_context_compute_score (ctx, &score2, true);
2816 : : else
2817 : 90 : score2 = score1;
2818 : 90 : if (score1 > max_score1)
2819 : : {
2820 : 35 : max_score1 = score1;
2821 : 35 : variant1 = attr1;
2822 : : }
2823 : 90 : if (score2 > max_score2)
2824 : : {
2825 : 35 : max_score2 = score2;
2826 : 35 : variant2 = attr1;
2827 : : }
2828 : : }
2829 : : else
2830 : : {
2831 : : variant1 = attr1;
2832 : : variant2 = attr1;
2833 : : }
2834 : : }
2835 : : /* If there is a disagreement on which variant has the highest score
2836 : : depending on whether it will be in a declare simd clone or not,
2837 : : punt for now and defer until after IPA where we will know that. */
2838 : 78 : return ((variant1 && variant1 == variant2)
2839 : 156 : ? TREE_PURPOSE (TREE_VALUE (variant1)) : base);
2840 : 194700 : }
2841 : :
2842 : : void
2843 : 2 : omp_lto_output_declare_variant_alt (lto_simple_output_block *ob,
2844 : : cgraph_node *node,
2845 : : lto_symtab_encoder_t encoder)
2846 : : {
2847 : 2 : gcc_assert (node->declare_variant_alt);
2848 : :
2849 : 2 : omp_declare_variant_base_entry entry;
2850 : 2 : entry.base = NULL;
2851 : 2 : entry.node = node;
2852 : 2 : entry.variants = NULL;
2853 : 2 : omp_declare_variant_base_entry *entryp
2854 : 2 : = omp_declare_variant_alt->find_with_hash (&entry, DECL_UID (node->decl));
2855 : 2 : gcc_assert (entryp);
2856 : :
2857 : 2 : int nbase = lto_symtab_encoder_lookup (encoder, entryp->base);
2858 : 2 : gcc_assert (nbase != LCC_NOT_FOUND);
2859 : 2 : streamer_write_hwi_stream (ob->main_stream, nbase);
2860 : :
2861 : 2 : streamer_write_hwi_stream (ob->main_stream, entryp->variants->length ());
2862 : :
2863 : 2 : unsigned int i;
2864 : 2 : omp_declare_variant_entry *varentry;
2865 : 8 : FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry)
2866 : : {
2867 : 6 : int nvar = lto_symtab_encoder_lookup (encoder, varentry->variant);
2868 : 6 : gcc_assert (nvar != LCC_NOT_FOUND);
2869 : 6 : streamer_write_hwi_stream (ob->main_stream, nvar);
2870 : :
2871 : 6 : for (score_wide_int *w = &varentry->score; ;
2872 : : w = &varentry->score_in_declare_simd_clone)
2873 : : {
2874 : 12 : unsigned len = w->get_len ();
2875 : 12 : streamer_write_hwi_stream (ob->main_stream, len);
2876 : 12 : const HOST_WIDE_INT *val = w->get_val ();
2877 : 24 : for (unsigned j = 0; j < len; j++)
2878 : 12 : streamer_write_hwi_stream (ob->main_stream, val[j]);
2879 : 12 : if (w == &varentry->score_in_declare_simd_clone)
2880 : : break;
2881 : : }
2882 : :
2883 : 6 : HOST_WIDE_INT cnt = -1;
2884 : 6 : HOST_WIDE_INT i = varentry->matches ? 1 : 0;
2885 : 6 : for (tree attr = DECL_ATTRIBUTES (entryp->base->decl);
2886 : 12 : attr; attr = TREE_CHAIN (attr), i += 2)
2887 : : {
2888 : 12 : attr = lookup_attribute ("omp declare variant base", attr);
2889 : 12 : if (attr == NULL_TREE)
2890 : : break;
2891 : :
2892 : 12 : if (varentry->ctx == TREE_VALUE (TREE_VALUE (attr)))
2893 : : {
2894 : : cnt = i;
2895 : : break;
2896 : : }
2897 : : }
2898 : :
2899 : 6 : gcc_assert (cnt != -1);
2900 : 6 : streamer_write_hwi_stream (ob->main_stream, cnt);
2901 : : }
2902 : 2 : }
2903 : :
2904 : : void
2905 : 2 : omp_lto_input_declare_variant_alt (lto_input_block *ib, cgraph_node *node,
2906 : : vec<symtab_node *> nodes)
2907 : : {
2908 : 2 : gcc_assert (node->declare_variant_alt);
2909 : 2 : omp_declare_variant_base_entry *entryp
2910 : 2 : = ggc_cleared_alloc<omp_declare_variant_base_entry> ();
2911 : 2 : entryp->base = dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
2912 : 2 : entryp->node = node;
2913 : 2 : unsigned int len = streamer_read_hwi (ib);
2914 : 2 : vec_alloc (entryp->variants, len);
2915 : :
2916 : 8 : for (unsigned int i = 0; i < len; i++)
2917 : : {
2918 : 6 : omp_declare_variant_entry varentry;
2919 : 6 : varentry.variant
2920 : 6 : = dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
2921 : 6 : for (score_wide_int *w = &varentry.score; ;
2922 : 6 : w = &varentry.score_in_declare_simd_clone)
2923 : : {
2924 : 12 : unsigned len2 = streamer_read_hwi (ib);
2925 : 12 : HOST_WIDE_INT arr[WIDE_INT_MAX_HWIS (1024)];
2926 : 12 : gcc_assert (len2 <= WIDE_INT_MAX_HWIS (1024));
2927 : 24 : for (unsigned int j = 0; j < len2; j++)
2928 : 12 : arr[j] = streamer_read_hwi (ib);
2929 : 12 : *w = score_wide_int::from_array (arr, len2, true);
2930 : 12 : if (w == &varentry.score_in_declare_simd_clone)
2931 : : break;
2932 : 6 : }
2933 : :
2934 : 6 : HOST_WIDE_INT cnt = streamer_read_hwi (ib);
2935 : 6 : HOST_WIDE_INT j = 0;
2936 : 6 : varentry.ctx = NULL_TREE;
2937 : 6 : varentry.matches = (cnt & 1) ? true : false;
2938 : 6 : cnt &= ~HOST_WIDE_INT_1;
2939 : 6 : for (tree attr = DECL_ATTRIBUTES (entryp->base->decl);
2940 : 12 : attr; attr = TREE_CHAIN (attr), j += 2)
2941 : : {
2942 : 12 : attr = lookup_attribute ("omp declare variant base", attr);
2943 : 12 : if (attr == NULL_TREE)
2944 : : break;
2945 : :
2946 : 12 : if (cnt == j)
2947 : : {
2948 : 6 : varentry.ctx = TREE_VALUE (TREE_VALUE (attr));
2949 : 6 : break;
2950 : : }
2951 : : }
2952 : 6 : gcc_assert (varentry.ctx != NULL_TREE);
2953 : 6 : entryp->variants->quick_push (varentry);
2954 : : }
2955 : 2 : if (omp_declare_variant_alt == NULL)
2956 : 2 : omp_declare_variant_alt
2957 : 2 : = hash_table<omp_declare_variant_alt_hasher>::create_ggc (64);
2958 : 2 : *omp_declare_variant_alt->find_slot_with_hash (entryp, DECL_UID (node->decl),
2959 : 2 : INSERT) = entryp;
2960 : 2 : }
2961 : :
2962 : : /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
2963 : : macro on gomp-constants.h. We do not check for overflow. */
2964 : :
2965 : : tree
2966 : 10238 : oacc_launch_pack (unsigned code, tree device, unsigned op)
2967 : : {
2968 : 10238 : tree res;
2969 : :
2970 : 10238 : res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
2971 : 10238 : if (device)
2972 : : {
2973 : 0 : device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
2974 : : device, build_int_cst (unsigned_type_node,
2975 : : GOMP_LAUNCH_DEVICE_SHIFT));
2976 : 0 : res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
2977 : : }
2978 : 10238 : return res;
2979 : : }
2980 : :
2981 : : /* Openacc compute grid dimension clauses are converted to an attribute
2982 : : attached to the function. This permits the target-side code to (a) massage
2983 : : the dimensions, (b) emit that data and (c) optimize. Non-constant
2984 : : dimensions are pushed onto ARGS.
2985 : :
2986 : : The attribute value is a TREE_LIST. A set of dimensions is
2987 : : represented as a list of INTEGER_CST. Those that are runtime
2988 : : exprs are represented as an INTEGER_CST of zero.
2989 : :
2990 : : TODO: Normally the attribute will just contain a single such list. If
2991 : : however it contains a list of lists, this will represent the use of
2992 : : device_type. Each member of the outer list is an assoc list of
2993 : : dimensions, keyed by the device type. The first entry will be the
2994 : : default. Well, that's the plan. */
2995 : :
2996 : : /* Replace any existing oacc fn attribute in ATTRIBS with updated
2997 : : dimensions. */
2998 : :
2999 : : tree
3000 : 19561 : oacc_replace_fn_attrib_attr (tree attribs, tree dims)
3001 : : {
3002 : 19561 : tree ident = get_identifier (OACC_FN_ATTRIB);
3003 : :
3004 : : /* If we happen to be present as the first attrib, drop it. */
3005 : 38064 : if (attribs && TREE_PURPOSE (attribs) == ident)
3006 : 9390 : attribs = TREE_CHAIN (attribs);
3007 : 19561 : return tree_cons (ident, dims, attribs);
3008 : : }
3009 : :
3010 : : /* Replace any existing oacc fn attribute on FN with updated
3011 : : dimensions. */
3012 : :
3013 : : void
3014 : 19224 : oacc_replace_fn_attrib (tree fn, tree dims)
3015 : : {
3016 : 19224 : DECL_ATTRIBUTES (fn)
3017 : 19224 : = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn), dims);
3018 : 19224 : }
3019 : :
3020 : : /* Scan CLAUSES for launch dimensions and attach them to the oacc
3021 : : function attribute. Push any that are non-constant onto the ARGS
3022 : : list, along with an appropriate GOMP_LAUNCH_DIM tag. */
3023 : :
3024 : : void
3025 : 9707 : oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args)
3026 : : {
3027 : : /* Must match GOMP_DIM ordering. */
3028 : 9707 : static const omp_clause_code ids[]
3029 : : = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
3030 : : OMP_CLAUSE_VECTOR_LENGTH };
3031 : 9707 : unsigned ix;
3032 : 9707 : tree dims[GOMP_DIM_MAX];
3033 : :
3034 : 9707 : tree attr = NULL_TREE;
3035 : 9707 : unsigned non_const = 0;
3036 : :
3037 : 38828 : for (ix = GOMP_DIM_MAX; ix--;)
3038 : : {
3039 : 29121 : tree clause = omp_find_clause (clauses, ids[ix]);
3040 : 29121 : tree dim = NULL_TREE;
3041 : :
3042 : 29121 : if (clause)
3043 : 3287 : dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
3044 : 29121 : dims[ix] = dim;
3045 : 29121 : if (dim && TREE_CODE (dim) != INTEGER_CST)
3046 : : {
3047 : 157 : dim = integer_zero_node;
3048 : 157 : non_const |= GOMP_DIM_MASK (ix);
3049 : : }
3050 : 29121 : attr = tree_cons (NULL_TREE, dim, attr);
3051 : : }
3052 : :
3053 : 9707 : oacc_replace_fn_attrib (fn, attr);
3054 : :
3055 : 9707 : if (non_const)
3056 : : {
3057 : : /* Push a dynamic argument set. */
3058 : 101 : args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
3059 : : NULL_TREE, non_const));
3060 : 404 : for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
3061 : 303 : if (non_const & GOMP_DIM_MASK (ix))
3062 : 157 : args->safe_push (dims[ix]);
3063 : : }
3064 : 9707 : }
3065 : :
3066 : : /* Verify OpenACC routine clauses.
3067 : :
3068 : : Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
3069 : : if it has already been marked in compatible way, and -1 if incompatible.
3070 : : Upon returning, the chain of clauses will contain exactly one clause
3071 : : specifying the level of parallelism. */
3072 : :
3073 : : int
3074 : 1202 : oacc_verify_routine_clauses (tree fndecl, tree *clauses, location_t loc,
3075 : : const char *routine_str)
3076 : : {
3077 : 1202 : tree c_level = NULL_TREE;
3078 : 1202 : tree c_nohost = NULL_TREE;
3079 : 1202 : tree c_p = NULL_TREE;
3080 : 3618 : for (tree c = *clauses; c; c_p = c, c = OMP_CLAUSE_CHAIN (c))
3081 : 2416 : switch (OMP_CLAUSE_CODE (c))
3082 : : {
3083 : 2317 : case OMP_CLAUSE_GANG:
3084 : 2317 : case OMP_CLAUSE_WORKER:
3085 : 2317 : case OMP_CLAUSE_VECTOR:
3086 : 2317 : case OMP_CLAUSE_SEQ:
3087 : 2317 : if (c_level == NULL_TREE)
3088 : : c_level = c;
3089 : 1496 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_CODE (c_level))
3090 : : {
3091 : : /* This has already been diagnosed in the front ends. */
3092 : : /* Drop the duplicate clause. */
3093 : 352 : gcc_checking_assert (c_p != NULL_TREE);
3094 : 352 : OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
3095 : 352 : c = c_p;
3096 : : }
3097 : : else
3098 : : {
3099 : 1144 : error_at (OMP_CLAUSE_LOCATION (c),
3100 : : "%qs specifies a conflicting level of parallelism",
3101 : 1144 : omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
3102 : 1144 : inform (OMP_CLAUSE_LOCATION (c_level),
3103 : : "... to the previous %qs clause here",
3104 : 1144 : omp_clause_code_name[OMP_CLAUSE_CODE (c_level)]);
3105 : : /* Drop the conflicting clause. */
3106 : 1144 : gcc_checking_assert (c_p != NULL_TREE);
3107 : 1144 : OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
3108 : 1144 : c = c_p;
3109 : : }
3110 : : break;
3111 : : case OMP_CLAUSE_NOHOST:
3112 : : /* Don't worry about duplicate clauses here. */
3113 : : c_nohost = c;
3114 : : break;
3115 : 0 : default:
3116 : 0 : gcc_unreachable ();
3117 : : }
3118 : 1202 : if (c_level == NULL_TREE)
3119 : : {
3120 : : /* Default to an implicit 'seq' clause. */
3121 : 381 : c_level = build_omp_clause (loc, OMP_CLAUSE_SEQ);
3122 : 381 : OMP_CLAUSE_CHAIN (c_level) = *clauses;
3123 : 381 : *clauses = c_level;
3124 : : }
3125 : : /* In *clauses, we now have exactly one clause specifying the level of
3126 : : parallelism. */
3127 : :
3128 : 1202 : tree attr
3129 : 1202 : = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl));
3130 : 1202 : if (attr != NULL_TREE)
3131 : : {
3132 : : /* Diagnose if "#pragma omp declare target" has also been applied. */
3133 : 429 : if (TREE_VALUE (attr) == NULL_TREE)
3134 : : {
3135 : : /* See <https://gcc.gnu.org/PR93465>; the semantics of combining
3136 : : OpenACC and OpenMP 'target' are not clear. */
3137 : 32 : error_at (loc,
3138 : : "cannot apply %<%s%> to %qD, which has also been"
3139 : : " marked with an OpenMP 'declare target' directive",
3140 : : routine_str, fndecl);
3141 : : /* Incompatible. */
3142 : 32 : return -1;
3143 : : }
3144 : :
3145 : : /* If a "#pragma acc routine" has already been applied, just verify
3146 : : this one for compatibility. */
3147 : : /* Collect previous directive's clauses. */
3148 : : tree c_level_p = NULL_TREE;
3149 : : tree c_nohost_p = NULL_TREE;
3150 : 850 : for (tree c = TREE_VALUE (attr); c; c = OMP_CLAUSE_CHAIN (c))
3151 : 453 : switch (OMP_CLAUSE_CODE (c))
3152 : : {
3153 : 397 : case OMP_CLAUSE_GANG:
3154 : 397 : case OMP_CLAUSE_WORKER:
3155 : 397 : case OMP_CLAUSE_VECTOR:
3156 : 397 : case OMP_CLAUSE_SEQ:
3157 : 397 : gcc_checking_assert (c_level_p == NULL_TREE);
3158 : : c_level_p = c;
3159 : : break;
3160 : 56 : case OMP_CLAUSE_NOHOST:
3161 : 56 : gcc_checking_assert (c_nohost_p == NULL_TREE);
3162 : : c_nohost_p = c;
3163 : : break;
3164 : 0 : default:
3165 : 0 : gcc_unreachable ();
3166 : : }
3167 : 397 : gcc_checking_assert (c_level_p != NULL_TREE);
3168 : : /* ..., and compare to current directive's, which we've already collected
3169 : : above. */
3170 : 397 : tree c_diag;
3171 : 397 : tree c_diag_p;
3172 : : /* Matching level of parallelism? */
3173 : 397 : if (OMP_CLAUSE_CODE (c_level) != OMP_CLAUSE_CODE (c_level_p))
3174 : : {
3175 : 97 : c_diag = c_level;
3176 : 97 : c_diag_p = c_level_p;
3177 : 97 : goto incompatible;
3178 : : }
3179 : : /* Matching 'nohost' clauses? */
3180 : 300 : if ((c_nohost == NULL_TREE) != (c_nohost_p == NULL_TREE))
3181 : : {
3182 : 56 : c_diag = c_nohost;
3183 : 56 : c_diag_p = c_nohost_p;
3184 : 56 : goto incompatible;
3185 : : }
3186 : : /* Compatible. */
3187 : : return 1;
3188 : :
3189 : 153 : incompatible:
3190 : 153 : if (c_diag != NULL_TREE)
3191 : 125 : error_at (OMP_CLAUSE_LOCATION (c_diag),
3192 : : "incompatible %qs clause when applying"
3193 : : " %<%s%> to %qD, which has already been"
3194 : : " marked with an OpenACC 'routine' directive",
3195 : 125 : omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)],
3196 : : routine_str, fndecl);
3197 : 28 : else if (c_diag_p != NULL_TREE)
3198 : 28 : error_at (loc,
3199 : : "missing %qs clause when applying"
3200 : : " %<%s%> to %qD, which has already been"
3201 : : " marked with an OpenACC 'routine' directive",
3202 : 28 : omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)],
3203 : : routine_str, fndecl);
3204 : : else
3205 : 0 : gcc_unreachable ();
3206 : 153 : if (c_diag_p != NULL_TREE)
3207 : 125 : inform (OMP_CLAUSE_LOCATION (c_diag_p),
3208 : : "... with %qs clause here",
3209 : 125 : omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)]);
3210 : : else
3211 : : {
3212 : : /* In the front ends, we don't preserve location information for the
3213 : : OpenACC routine directive itself. However, that of c_level_p
3214 : : should be close. */
3215 : 28 : location_t loc_routine = OMP_CLAUSE_LOCATION (c_level_p);
3216 : 28 : inform (loc_routine, "... without %qs clause near to here",
3217 : 28 : omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)]);
3218 : : }
3219 : : /* Incompatible. */
3220 : 153 : return -1;
3221 : : }
3222 : :
3223 : : return 0;
3224 : : }
3225 : :
3226 : : /* Process the OpenACC 'routine' directive clauses to generate an attribute
3227 : : for the level of parallelism. All dimensions have a size of zero
3228 : : (dynamic). TREE_PURPOSE is set to indicate whether that dimension
3229 : : can have a loop partitioned on it. non-zero indicates
3230 : : yes, zero indicates no. By construction once a non-zero has been
3231 : : reached, further inner dimensions must also be non-zero. We set
3232 : : TREE_VALUE to zero for the dimensions that may be partitioned and
3233 : : 1 for the other ones -- if a loop is (erroneously) spawned at
3234 : : an outer level, we don't want to try and partition it. */
3235 : :
3236 : : tree
3237 : 1102 : oacc_build_routine_dims (tree clauses)
3238 : : {
3239 : : /* Must match GOMP_DIM ordering. */
3240 : 1102 : static const omp_clause_code ids[]
3241 : : = {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
3242 : 1102 : int ix;
3243 : 1102 : int level = -1;
3244 : :
3245 : 2247 : for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
3246 : 2249 : for (ix = GOMP_DIM_MAX + 1; ix--;)
3247 : 2206 : if (OMP_CLAUSE_CODE (clauses) == ids[ix])
3248 : : {
3249 : : level = ix;
3250 : : break;
3251 : : }
3252 : 1102 : gcc_checking_assert (level >= 0);
3253 : :
3254 : : tree dims = NULL_TREE;
3255 : :
3256 : 4408 : for (ix = GOMP_DIM_MAX; ix--;)
3257 : 3306 : dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
3258 : 3306 : build_int_cst (integer_type_node, ix < level), dims);
3259 : :
3260 : 1102 : return dims;
3261 : : }
3262 : :
3263 : : /* Retrieve the oacc function attrib and return it. Non-oacc
3264 : : functions will return NULL. */
3265 : :
3266 : : tree
3267 : 302310 : oacc_get_fn_attrib (tree fn)
3268 : : {
3269 : 302310 : return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
3270 : : }
3271 : :
3272 : : /* Return true if FN is an OpenMP or OpenACC offloading function. */
3273 : :
3274 : : bool
3275 : 588 : offloading_function_p (tree fn)
3276 : : {
3277 : 588 : tree attrs = DECL_ATTRIBUTES (fn);
3278 : 588 : return (lookup_attribute ("omp declare target", attrs)
3279 : 588 : || lookup_attribute ("omp target entrypoint", attrs));
3280 : : }
3281 : :
3282 : : /* Extract an oacc execution dimension from FN. FN must be an
3283 : : offloaded function or routine that has already had its execution
3284 : : dimensions lowered to the target-specific values. */
3285 : :
3286 : : int
3287 : 57156 : oacc_get_fn_dim_size (tree fn, int axis)
3288 : : {
3289 : 57156 : tree attrs = oacc_get_fn_attrib (fn);
3290 : :
3291 : 57156 : gcc_assert (axis < GOMP_DIM_MAX);
3292 : :
3293 : 57156 : tree dims = TREE_VALUE (attrs);
3294 : 115903 : while (axis--)
3295 : 58747 : dims = TREE_CHAIN (dims);
3296 : :
3297 : 57156 : int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
3298 : :
3299 : 57156 : return size;
3300 : : }
3301 : :
3302 : : /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
3303 : : IFN_GOACC_DIM_SIZE call. */
3304 : :
3305 : : int
3306 : 84701 : oacc_get_ifn_dim_arg (const gimple *stmt)
3307 : : {
3308 : 84701 : gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
3309 : : || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
3310 : 84701 : tree arg = gimple_call_arg (stmt, 0);
3311 : 84701 : HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
3312 : :
3313 : 84701 : gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
3314 : 84701 : return (int) axis;
3315 : : }
3316 : :
3317 : : /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
3318 : : as appropriate. */
3319 : :
3320 : : tree
3321 : 283257 : omp_build_component_ref (tree obj, tree field)
3322 : : {
3323 : 283257 : tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
3324 : 283257 : if (TREE_THIS_VOLATILE (field))
3325 : 62 : TREE_THIS_VOLATILE (ret) |= 1;
3326 : 283257 : if (TREE_READONLY (field))
3327 : 0 : TREE_READONLY (ret) |= 1;
3328 : 283257 : return ret;
3329 : : }
3330 : :
3331 : : /* Return true if NAME is the name of an omp_* runtime API call. */
3332 : : bool
3333 : 7223 : omp_runtime_api_procname (const char *name)
3334 : : {
3335 : 7223 : if (!startswith (name, "omp_"))
3336 : : return false;
3337 : :
3338 : : static const char *omp_runtime_apis[] =
3339 : : {
3340 : : /* This array has 3 sections. First omp_* calls that don't
3341 : : have any suffixes. */
3342 : : "aligned_alloc",
3343 : : "aligned_calloc",
3344 : : "alloc",
3345 : : "calloc",
3346 : : "free",
3347 : : "get_interop_int",
3348 : : "get_interop_ptr",
3349 : : "get_mapped_ptr",
3350 : : "get_num_interop_properties",
3351 : : "realloc",
3352 : : "target_alloc",
3353 : : "target_associate_ptr",
3354 : : "target_disassociate_ptr",
3355 : : "target_free",
3356 : : "target_is_accessible",
3357 : : "target_is_present",
3358 : : "target_memcpy",
3359 : : "target_memcpy_async",
3360 : : "target_memcpy_rect",
3361 : : "target_memcpy_rect_async",
3362 : : NULL,
3363 : : /* Now omp_* calls that are available as omp_* and omp_*_; however, the
3364 : : DECL_NAME is always omp_* without tailing underscore. */
3365 : : "capture_affinity",
3366 : : "destroy_allocator",
3367 : : "destroy_lock",
3368 : : "destroy_nest_lock",
3369 : : "display_affinity",
3370 : : "fulfill_event",
3371 : : "get_active_level",
3372 : : "get_affinity_format",
3373 : : "get_cancellation",
3374 : : "get_default_allocator",
3375 : : "get_default_device",
3376 : : "get_device_from_uid",
3377 : : "get_device_num",
3378 : : "get_dynamic",
3379 : : "get_initial_device",
3380 : : "get_interop_name",
3381 : : "get_interop_rc_desc",
3382 : : "get_interop_str",
3383 : : "get_interop_type_desc",
3384 : : "get_level",
3385 : : "get_max_active_levels",
3386 : : "get_max_task_priority",
3387 : : "get_max_teams",
3388 : : "get_max_threads",
3389 : : "get_nested",
3390 : : "get_num_devices",
3391 : : "get_num_places",
3392 : : "get_num_procs",
3393 : : "get_num_teams",
3394 : : "get_num_threads",
3395 : : "get_partition_num_places",
3396 : : "get_place_num",
3397 : : "get_proc_bind",
3398 : : "get_supported_active_levels",
3399 : : "get_team_num",
3400 : : "get_teams_thread_limit",
3401 : : "get_thread_limit",
3402 : : "get_thread_num",
3403 : : "get_wtick",
3404 : : "get_wtime",
3405 : : "in_explicit_task",
3406 : : "in_final",
3407 : : "in_parallel",
3408 : : "init_lock",
3409 : : "init_nest_lock",
3410 : : "is_initial_device",
3411 : : "pause_resource",
3412 : : "pause_resource_all",
3413 : : "set_affinity_format",
3414 : : "set_default_allocator",
3415 : : "set_lock",
3416 : : "set_nest_lock",
3417 : : "test_lock",
3418 : : "test_nest_lock",
3419 : : "unset_lock",
3420 : : "unset_nest_lock",
3421 : : NULL,
3422 : : /* And finally calls available as omp_*, omp_*_ and omp_*_8_; however,
3423 : : as DECL_NAME only omp_* and omp_*_8 appear. */
3424 : : "display_env",
3425 : : "get_ancestor_thread_num",
3426 : : "get_uid_from_device",
3427 : : "get_partition_place_nums",
3428 : : "get_place_num_procs",
3429 : : "get_place_proc_ids",
3430 : : "get_schedule",
3431 : : "get_team_size",
3432 : : "init_allocator",
3433 : : "set_default_device",
3434 : : "set_dynamic",
3435 : : "set_max_active_levels",
3436 : : "set_nested",
3437 : : "set_num_teams",
3438 : : "set_num_threads",
3439 : : "set_schedule",
3440 : : "set_teams_thread_limit"
3441 : : };
3442 : :
3443 : : int mode = 0;
3444 : 41167 : for (unsigned i = 0; i < ARRAY_SIZE (omp_runtime_apis); i++)
3445 : : {
3446 : 41166 : if (omp_runtime_apis[i] == NULL)
3447 : : {
3448 : 805 : mode++;
3449 : 805 : continue;
3450 : : }
3451 : 40361 : size_t len = strlen (omp_runtime_apis[i]);
3452 : 40361 : if (strncmp (name + 4, omp_runtime_apis[i], len) == 0
3453 : 917 : && (name[4 + len] == '\0'
3454 : 3 : || (mode > 1 && strcmp (name + 4 + len, "_8") == 0)))
3455 : : return true;
3456 : : }
3457 : : return false;
3458 : : }
3459 : :
3460 : : /* Return true if FNDECL is an omp_* runtime API call. */
3461 : :
3462 : : bool
3463 : 7380 : omp_runtime_api_call (const_tree fndecl)
3464 : : {
3465 : 7380 : tree declname = DECL_NAME (fndecl);
3466 : 7380 : if (!declname
3467 : 7380 : || (DECL_CONTEXT (fndecl) != NULL_TREE
3468 : 5368 : && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
3469 : 14184 : || !TREE_PUBLIC (fndecl))
3470 : : return false;
3471 : 6745 : return omp_runtime_api_procname (IDENTIFIER_POINTER (declname));
3472 : : }
3473 : :
3474 : : /* See "Additional Definitions for the OpenMP API Specification" document;
3475 : : associated IDs are 1, 2, ... */
3476 : : static const char* omp_interop_fr_str[] = {"cuda", "cuda_driver", "opencl",
3477 : : "sycl", "hip", "level_zero", "hsa"};
3478 : :
3479 : : /* Returns the foreign-runtime ID if found or 0 otherwise. */
3480 : :
3481 : : int
3482 : 28 : omp_get_fr_id_from_name (const char *str)
3483 : : {
3484 : 28 : static_assert (GOMP_INTEROP_IFR_LAST == ARRAY_SIZE (omp_interop_fr_str), "");
3485 : :
3486 : 107 : for (unsigned i = 0; i < ARRAY_SIZE (omp_interop_fr_str); ++i)
3487 : 105 : if (!strcmp (str, omp_interop_fr_str[i]))
3488 : 26 : return i + 1;
3489 : : return 0;
3490 : : }
3491 : :
3492 : : /* Returns the string value to a foreign-runtime integer value or NULL if value
3493 : : is not known. */
3494 : :
3495 : : const char *
3496 : 0 : omp_get_name_from_fr_id (int fr_id)
3497 : : {
3498 : 0 : if (fr_id < 1 || fr_id > (int) ARRAY_SIZE (omp_interop_fr_str))
3499 : : return NULL;
3500 : 0 : return omp_interop_fr_str[fr_id-1];
3501 : : }
3502 : :
3503 : : namespace omp_addr_tokenizer {
3504 : :
3505 : : /* We scan an expression by recursive descent, and build a vector of
3506 : : "omp_addr_token *" pointers representing a "parsed" version of the
3507 : : expression. The grammar we use is something like this:
3508 : :
3509 : : expr0::
3510 : : expr [section-access]
3511 : :
3512 : : expr::
3513 : : structured-expr access-method
3514 : : | array-base access-method
3515 : :
3516 : : structured-expr::
3517 : : structure-base component-selector
3518 : :
3519 : : arbitrary-expr::
3520 : : (anything else)
3521 : :
3522 : : structure-base::
3523 : : DECL access-method
3524 : : | structured-expr access-method
3525 : : | arbitrary-expr access-method
3526 : :
3527 : : array-base::
3528 : : DECL
3529 : : | arbitrary-expr
3530 : :
3531 : : access-method::
3532 : : DIRECT
3533 : : | REF
3534 : : | POINTER
3535 : : | REF_TO_POINTER
3536 : : | POINTER_OFFSET
3537 : : | REF_TO_POINTER_OFFSET
3538 : : | INDEXED_ARRAY
3539 : : | INDEXED_REF_TO_ARRAY
3540 : : | index-expr
3541 : :
3542 : : index-expr::
3543 : : INDEX_EXPR access-method
3544 : :
3545 : : component-selector::
3546 : : component-selector COMPONENT_REF
3547 : : | component-selector ARRAY_REF
3548 : : | COMPONENT_REF
3549 : :
3550 : : This tokenized form is then used both in parsing, for OpenMP clause
3551 : : expansion (for C and C++) and in gimplify.cc for sibling-list handling
3552 : : (for C, C++ and Fortran). */
3553 : :
3554 : 27970 : omp_addr_token::omp_addr_token (token_type t, tree e)
3555 : 27970 : : type(t), expr(e)
3556 : : {
3557 : 27970 : }
3558 : :
3559 : 111934 : omp_addr_token::omp_addr_token (access_method_kinds k, tree e)
3560 : 111934 : : type(ACCESS_METHOD), expr(e)
3561 : : {
3562 : 111934 : u.access_kind = k;
3563 : 111934 : }
3564 : :
3565 : 86268 : omp_addr_token::omp_addr_token (token_type t, structure_base_kinds k, tree e)
3566 : 86268 : : type(t), expr(e)
3567 : : {
3568 : 86268 : u.structure_base_kind = k;
3569 : 86268 : }
3570 : :
3571 : : static bool
3572 : 86271 : omp_parse_component_selector (tree *expr0)
3573 : : {
3574 : 86271 : tree expr = *expr0;
3575 : 86271 : tree last_component = NULL_TREE;
3576 : :
3577 : 86271 : while (TREE_CODE (expr) == COMPONENT_REF
3578 : 121183 : || TREE_CODE (expr) == ARRAY_REF)
3579 : : {
3580 : 34912 : if (TREE_CODE (expr) == COMPONENT_REF)
3581 : 33147 : last_component = expr;
3582 : :
3583 : 34912 : expr = TREE_OPERAND (expr, 0);
3584 : :
3585 : 34912 : if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
3586 : : break;
3587 : : }
3588 : :
3589 : 86271 : if (!last_component)
3590 : : return false;
3591 : :
3592 : 27970 : *expr0 = last_component;
3593 : 27970 : return true;
3594 : : }
3595 : :
3596 : : /* This handles references that have had convert_from_reference called on
3597 : : them, and also those that haven't. */
3598 : :
3599 : : static bool
3600 : 145408 : omp_parse_ref (tree *expr0)
3601 : : {
3602 : 145408 : tree expr = *expr0;
3603 : :
3604 : 145408 : if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
3605 : : return true;
3606 : 141433 : else if ((TREE_CODE (expr) == INDIRECT_REF
3607 : 103752 : || (TREE_CODE (expr) == MEM_REF
3608 : 0 : && integer_zerop (TREE_OPERAND (expr, 1))))
3609 : 141433 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
3610 : : {
3611 : 9313 : *expr0 = TREE_OPERAND (expr, 0);
3612 : 9313 : return true;
3613 : : }
3614 : :
3615 : : return false;
3616 : : }
3617 : :
3618 : : static bool
3619 : 102457 : omp_parse_pointer (tree *expr0, bool *has_offset)
3620 : : {
3621 : 102457 : tree expr = *expr0;
3622 : :
3623 : 102457 : *has_offset = false;
3624 : :
3625 : 102457 : if ((TREE_CODE (expr) == INDIRECT_REF
3626 : 75186 : || (TREE_CODE (expr) == MEM_REF
3627 : 0 : && integer_zerop (TREE_OPERAND (expr, 1))))
3628 : 102457 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == POINTER_TYPE)
3629 : : {
3630 : 27271 : expr = TREE_OPERAND (expr, 0);
3631 : :
3632 : : /* The Fortran FE sometimes emits a no-op cast here. */
3633 : 27271 : STRIP_NOPS (expr);
3634 : :
3635 : 30189 : while (1)
3636 : : {
3637 : 30189 : if (TREE_CODE (expr) == COMPOUND_EXPR)
3638 : : {
3639 : 101 : expr = TREE_OPERAND (expr, 1);
3640 : 101 : STRIP_NOPS (expr);
3641 : : }
3642 : 30088 : else if (TREE_CODE (expr) == SAVE_EXPR)
3643 : 89 : expr = TREE_OPERAND (expr, 0);
3644 : 29999 : else if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
3645 : : {
3646 : 2728 : *has_offset = true;
3647 : 2728 : expr = TREE_OPERAND (expr, 0);
3648 : : }
3649 : : else
3650 : : break;
3651 : : }
3652 : :
3653 : 27271 : STRIP_NOPS (expr);
3654 : :
3655 : 27271 : *expr0 = expr;
3656 : 27271 : return true;
3657 : : }
3658 : :
3659 : : return false;
3660 : : }
3661 : :
3662 : : static bool
3663 : 111934 : omp_parse_access_method (tree *expr0, enum access_method_kinds *kind)
3664 : : {
3665 : 111934 : tree expr = *expr0;
3666 : 111934 : bool has_offset;
3667 : :
3668 : 111934 : if (omp_parse_ref (&expr))
3669 : 9477 : *kind = ACCESS_REF;
3670 : 102457 : else if (omp_parse_pointer (&expr, &has_offset))
3671 : : {
3672 : 27271 : if (omp_parse_ref (&expr))
3673 : 5574 : *kind = has_offset ? ACCESS_REF_TO_POINTER_OFFSET
3674 : : : ACCESS_REF_TO_POINTER;
3675 : : else
3676 : 46240 : *kind = has_offset ? ACCESS_POINTER_OFFSET : ACCESS_POINTER;
3677 : : }
3678 : 75186 : else if (TREE_CODE (expr) == ARRAY_REF)
3679 : : {
3680 : 12690 : while (TREE_CODE (expr) == ARRAY_REF)
3681 : 6487 : expr = TREE_OPERAND (expr, 0);
3682 : 6203 : if (omp_parse_ref (&expr))
3683 : 640 : *kind = ACCESS_INDEXED_REF_TO_ARRAY;
3684 : : else
3685 : 5563 : *kind = ACCESS_INDEXED_ARRAY;
3686 : : }
3687 : : else
3688 : 68983 : *kind = ACCESS_DIRECT;
3689 : :
3690 : 111934 : STRIP_NOPS (expr);
3691 : :
3692 : 111934 : *expr0 = expr;
3693 : 111934 : return true;
3694 : : }
3695 : :
3696 : : static bool
3697 : 111934 : omp_parse_access_methods (vec<omp_addr_token *> &addr_tokens, tree *expr0)
3698 : : {
3699 : 111934 : tree expr = *expr0;
3700 : 111934 : enum access_method_kinds kind;
3701 : 111934 : tree am_expr;
3702 : :
3703 : 111934 : if (omp_parse_access_method (&expr, &kind))
3704 : 111934 : am_expr = expr;
3705 : :
3706 : 111934 : if (TREE_CODE (expr) == INDIRECT_REF
3707 : 111934 : || TREE_CODE (expr) == MEM_REF
3708 : 110837 : || TREE_CODE (expr) == ARRAY_REF)
3709 : 1488 : omp_parse_access_methods (addr_tokens, &expr);
3710 : :
3711 : 111934 : addr_tokens.safe_push (new omp_addr_token (kind, am_expr));
3712 : :
3713 : 111934 : *expr0 = expr;
3714 : 111934 : return true;
3715 : : }
3716 : :
3717 : : static bool omp_parse_structured_expr (vec<omp_addr_token *> &, tree *);
3718 : :
3719 : : static bool
3720 : 86268 : omp_parse_structure_base (vec<omp_addr_token *> &addr_tokens,
3721 : : tree *expr0, structure_base_kinds *kind,
3722 : : vec<omp_addr_token *> &base_access_tokens,
3723 : : bool allow_structured = true)
3724 : : {
3725 : 86268 : tree expr = *expr0;
3726 : :
3727 : 86268 : if (allow_structured)
3728 : 27970 : omp_parse_access_methods (base_access_tokens, &expr);
3729 : :
3730 : 86268 : if (DECL_P (expr))
3731 : : {
3732 : 81953 : *kind = BASE_DECL;
3733 : 81953 : return true;
3734 : : }
3735 : :
3736 : 4315 : if (allow_structured && omp_parse_structured_expr (addr_tokens, &expr))
3737 : : {
3738 : 3792 : *kind = BASE_COMPONENT_EXPR;
3739 : 3792 : *expr0 = expr;
3740 : 3792 : return true;
3741 : : }
3742 : :
3743 : 523 : *kind = BASE_ARBITRARY_EXPR;
3744 : 523 : *expr0 = expr;
3745 : 523 : return true;
3746 : : }
3747 : :
3748 : : static bool
3749 : 86271 : omp_parse_structured_expr (vec<omp_addr_token *> &addr_tokens, tree *expr0)
3750 : : {
3751 : 86271 : tree expr = *expr0;
3752 : 86271 : tree base_component = NULL_TREE;
3753 : 86271 : structure_base_kinds struct_base_kind;
3754 : 86271 : auto_vec<omp_addr_token *> base_access_tokens;
3755 : :
3756 : 86271 : if (omp_parse_component_selector (&expr))
3757 : 27970 : base_component = expr;
3758 : : else
3759 : : return false;
3760 : :
3761 : 27970 : gcc_assert (TREE_CODE (expr) == COMPONENT_REF);
3762 : 27970 : expr = TREE_OPERAND (expr, 0);
3763 : :
3764 : 27970 : tree structure_base = expr;
3765 : :
3766 : 27970 : if (!omp_parse_structure_base (addr_tokens, &expr, &struct_base_kind,
3767 : : base_access_tokens))
3768 : : return false;
3769 : :
3770 : 27970 : addr_tokens.safe_push (new omp_addr_token (STRUCTURE_BASE, struct_base_kind,
3771 : 27970 : structure_base));
3772 : 27970 : addr_tokens.safe_splice (base_access_tokens);
3773 : 27970 : addr_tokens.safe_push (new omp_addr_token (COMPONENT_SELECTOR,
3774 : 27970 : base_component));
3775 : :
3776 : 27970 : *expr0 = expr;
3777 : :
3778 : 27970 : return true;
3779 : 86271 : }
3780 : :
3781 : : static bool
3782 : 58298 : omp_parse_array_expr (vec<omp_addr_token *> &addr_tokens, tree *expr0)
3783 : : {
3784 : 58298 : tree expr = *expr0;
3785 : 58298 : structure_base_kinds s_kind;
3786 : 58298 : auto_vec<omp_addr_token *> base_access_tokens;
3787 : :
3788 : 58298 : if (!omp_parse_structure_base (addr_tokens, &expr, &s_kind,
3789 : : base_access_tokens, false))
3790 : : return false;
3791 : :
3792 : 58298 : addr_tokens.safe_push (new omp_addr_token (ARRAY_BASE, s_kind, expr));
3793 : 58298 : addr_tokens.safe_splice (base_access_tokens);
3794 : :
3795 : 58298 : *expr0 = expr;
3796 : 58298 : return true;
3797 : 58298 : }
3798 : :
3799 : : /* Return TRUE if the ACCESS_METHOD token at index 'i' has a further
3800 : : ACCESS_METHOD chained after it (e.g., if we're processing an expression
3801 : : containing multiple pointer indirections). */
3802 : :
3803 : : bool
3804 : 44217 : omp_access_chain_p (vec<omp_addr_token *> &addr_tokens, unsigned i)
3805 : : {
3806 : 44217 : gcc_assert (addr_tokens[i]->type == ACCESS_METHOD);
3807 : 44217 : return (i + 1 < addr_tokens.length ()
3808 : 44217 : && addr_tokens[i + 1]->type == ACCESS_METHOD);
3809 : : }
3810 : :
3811 : : /* Return the address of the object accessed by the ACCESS_METHOD token
3812 : : at 'i': either of the next access method's expr, or of EXPR if we're at
3813 : : the end of the list of tokens. */
3814 : :
3815 : : tree
3816 : 4178 : omp_accessed_addr (vec<omp_addr_token *> &addr_tokens, unsigned i, tree expr)
3817 : : {
3818 : 8356 : if (i + 1 < addr_tokens.length ())
3819 : 26 : return build_fold_addr_expr (addr_tokens[i + 1]->expr);
3820 : : else
3821 : 4152 : return build_fold_addr_expr (expr);
3822 : : }
3823 : :
3824 : : } /* namespace omp_addr_tokenizer. */
3825 : :
3826 : : bool
3827 : 82476 : omp_parse_expr (vec<omp_addr_token *> &addr_tokens, tree expr)
3828 : : {
3829 : 82476 : using namespace omp_addr_tokenizer;
3830 : 82476 : auto_vec<omp_addr_token *> expr_access_tokens;
3831 : :
3832 : 82476 : if (!omp_parse_access_methods (expr_access_tokens, &expr))
3833 : : return false;
3834 : :
3835 : 82476 : if (omp_parse_structured_expr (addr_tokens, &expr))
3836 : : ;
3837 : 58298 : else if (omp_parse_array_expr (addr_tokens, &expr))
3838 : : ;
3839 : : else
3840 : : return false;
3841 : :
3842 : 82476 : addr_tokens.safe_splice (expr_access_tokens);
3843 : :
3844 : 82476 : return true;
3845 : 82476 : }
3846 : :
3847 : : DEBUG_FUNCTION void
3848 : 0 : debug_omp_tokenized_addr (vec<omp_addr_token *> &addr_tokens,
3849 : : bool with_exprs)
3850 : : {
3851 : 0 : using namespace omp_addr_tokenizer;
3852 : 0 : const char *sep = with_exprs ? " " : "";
3853 : :
3854 : 0 : for (auto e : addr_tokens)
3855 : : {
3856 : 0 : const char *pfx = "";
3857 : :
3858 : 0 : fputs (sep, stderr);
3859 : :
3860 : 0 : switch (e->type)
3861 : : {
3862 : 0 : case COMPONENT_SELECTOR:
3863 : 0 : fputs ("component_selector", stderr);
3864 : 0 : break;
3865 : 0 : case ACCESS_METHOD:
3866 : 0 : switch (e->u.access_kind)
3867 : : {
3868 : 0 : case ACCESS_DIRECT:
3869 : 0 : fputs ("access_direct", stderr);
3870 : 0 : break;
3871 : 0 : case ACCESS_REF:
3872 : 0 : fputs ("access_ref", stderr);
3873 : 0 : break;
3874 : 0 : case ACCESS_POINTER:
3875 : 0 : fputs ("access_pointer", stderr);
3876 : 0 : break;
3877 : 0 : case ACCESS_POINTER_OFFSET:
3878 : 0 : fputs ("access_pointer_offset", stderr);
3879 : 0 : break;
3880 : 0 : case ACCESS_REF_TO_POINTER:
3881 : 0 : fputs ("access_ref_to_pointer", stderr);
3882 : 0 : break;
3883 : 0 : case ACCESS_REF_TO_POINTER_OFFSET:
3884 : 0 : fputs ("access_ref_to_pointer_offset", stderr);
3885 : 0 : break;
3886 : 0 : case ACCESS_INDEXED_ARRAY:
3887 : 0 : fputs ("access_indexed_array", stderr);
3888 : 0 : break;
3889 : 0 : case ACCESS_INDEXED_REF_TO_ARRAY:
3890 : 0 : fputs ("access_indexed_ref_to_array", stderr);
3891 : 0 : break;
3892 : : }
3893 : : break;
3894 : 0 : case ARRAY_BASE:
3895 : 0 : case STRUCTURE_BASE:
3896 : 0 : pfx = e->type == ARRAY_BASE ? "array_" : "struct_";
3897 : 0 : switch (e->u.structure_base_kind)
3898 : : {
3899 : 0 : case BASE_DECL:
3900 : 0 : fprintf (stderr, "%sbase_decl", pfx);
3901 : 0 : break;
3902 : 0 : case BASE_COMPONENT_EXPR:
3903 : 0 : fputs ("base_component_expr", stderr);
3904 : 0 : break;
3905 : 0 : case BASE_ARBITRARY_EXPR:
3906 : 0 : fprintf (stderr, "%sbase_arbitrary_expr", pfx);
3907 : 0 : break;
3908 : : }
3909 : : break;
3910 : : }
3911 : 0 : if (with_exprs)
3912 : : {
3913 : 0 : fputs (" [", stderr);
3914 : 0 : print_generic_expr (stderr, e->expr);
3915 : 0 : fputc (']', stderr);
3916 : 0 : sep = ",\n ";
3917 : : }
3918 : : else
3919 : : sep = " ";
3920 : : }
3921 : :
3922 : 0 : fputs ("\n", stderr);
3923 : 0 : }
3924 : :
3925 : : /* Return number of iterations of loop I in FOR_STMT. If PSTEP is non-NULL,
3926 : : *PSTEP will be the loop step. */
3927 : :
3928 : : tree
3929 : 2647 : omp_loop_number_of_iterations (tree for_stmt, int i, tree *pstep)
3930 : : {
3931 : 2647 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
3932 : 2647 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
3933 : 2647 : tree decl = TREE_OPERAND (t, 0);
3934 : 2647 : tree n1 = TREE_OPERAND (t, 1);
3935 : 2647 : tree type = TREE_TYPE (decl);
3936 : 2647 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
3937 : 2647 : gcc_assert (COMPARISON_CLASS_P (cond));
3938 : 2647 : gcc_assert (TREE_OPERAND (cond, 0) == decl);
3939 : 2647 : tree_code cond_code = TREE_CODE (cond);
3940 : 2647 : tree n2 = TREE_OPERAND (cond, 1);
3941 : 2647 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
3942 : 2647 : tree step = NULL_TREE;
3943 : 2647 : switch (TREE_CODE (t))
3944 : : {
3945 : 1141 : case PREINCREMENT_EXPR:
3946 : 1141 : case POSTINCREMENT_EXPR:
3947 : 1141 : gcc_assert (!POINTER_TYPE_P (type));
3948 : 1141 : gcc_assert (TREE_OPERAND (t, 0) == decl);
3949 : 1141 : step = build_int_cst (type, 1);
3950 : 1141 : break;
3951 : 42 : case PREDECREMENT_EXPR:
3952 : 42 : case POSTDECREMENT_EXPR:
3953 : 42 : gcc_assert (!POINTER_TYPE_P (type));
3954 : 42 : gcc_assert (TREE_OPERAND (t, 0) == decl);
3955 : 42 : step = build_int_cst (type, -1);
3956 : 42 : break;
3957 : 1464 : case MODIFY_EXPR:
3958 : 1464 : gcc_assert (TREE_OPERAND (t, 0) == decl);
3959 : 1464 : t = TREE_OPERAND (t, 1);
3960 : 1464 : switch (TREE_CODE (t))
3961 : : {
3962 : 1389 : case PLUS_EXPR:
3963 : 1389 : if (TREE_OPERAND (t, 1) == decl)
3964 : : {
3965 : 3 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
3966 : 3 : TREE_OPERAND (t, 0) = decl;
3967 : : }
3968 : : /* FALLTHRU */
3969 : : case POINTER_PLUS_EXPR:
3970 : : case MINUS_EXPR:
3971 : 1464 : step = omp_get_for_step_from_incr (EXPR_LOCATION (t), t);
3972 : 1464 : break;
3973 : 0 : default:
3974 : 0 : gcc_unreachable ();
3975 : : }
3976 : 1464 : break;
3977 : 0 : default:
3978 : 0 : gcc_unreachable ();
3979 : : }
3980 : 2647 : omp_adjust_for_condition (EXPR_LOCATION (for_stmt), &cond_code, &n2,
3981 : : decl, step);
3982 : 2647 : if (pstep)
3983 : 2099 : *pstep = step;
3984 : 2647 : if (INTEGRAL_TYPE_P (type)
3985 : 2647 : && TYPE_PRECISION (type) < TYPE_PRECISION (long_long_integer_type_node))
3986 : : {
3987 : 2538 : n1 = fold_convert (long_long_integer_type_node, n1);
3988 : 2538 : n2 = fold_convert (long_long_integer_type_node, n2);
3989 : 2538 : step = fold_convert (long_long_integer_type_node, step);
3990 : : }
3991 : 2647 : if (cond_code == LT_EXPR
3992 : 156 : || POINTER_TYPE_P (type)
3993 : 2783 : || !TYPE_UNSIGNED (TREE_TYPE (n1)))
3994 : : {
3995 : 2647 : if (POINTER_TYPE_P (type))
3996 : 60 : t = fold_build2 (POINTER_DIFF_EXPR, ssizetype, n2, n1);
3997 : : else
3998 : 2587 : t = fold_build2 (MINUS_EXPR, TREE_TYPE (n1), n2, n1);
3999 : 2647 : t = fold_build2 (CEIL_DIV_EXPR, TREE_TYPE (t), t, step);
4000 : : }
4001 : : else
4002 : : {
4003 : 0 : t = fold_build2 (MINUS_EXPR, type, n1, n2);
4004 : 0 : t = fold_build2 (CEIL_DIV_EXPR, type, t,
4005 : : fold_build1 (NEGATE_EXPR, type, step));
4006 : : }
4007 : 2647 : return t;
4008 : : }
4009 : :
4010 : : /* Tile transformation:
4011 : : Original loop:
4012 : :
4013 : : #pragma omp tile sizes(16, 32)
4014 : : for (i = 0; i < k; ++i)
4015 : : for (j = 0; j < 128; j += 2)
4016 : : {
4017 : : baz (i, j);
4018 : : }
4019 : :
4020 : : Transformed loop:
4021 : : #pragma omp tile sizes(16, 32)
4022 : : for (i.0 = 0; i.0 < k; i.0 += 16)
4023 : : for (j.0 = 0; j.0 < 128; j.0 += 64)
4024 : : {
4025 : : i = i.0;
4026 : : i.1 = MIN_EXPR <i.0 + 16, k>;
4027 : : goto <D.2783>;
4028 : : <D.2782>:;
4029 : : j = j.0;
4030 : : j.1 = j.0 + 32;
4031 : : goto <D.2786>;
4032 : : <D.2785>:;
4033 : : {
4034 : : baz (i, j);
4035 : : }
4036 : : j += 2;
4037 : : <D.2786>:;
4038 : : if (j < j.1) goto <D.2785>; else goto <D.2787>;
4039 : : <D.2787>:;
4040 : : ++i;
4041 : : <D.2783>:;
4042 : : if (i < i.1) goto <D.2782>; else goto <D.2784>;
4043 : : <D.2784>:;
4044 : : }
4045 : :
4046 : : where the grid loops have canonical form, but the inner
4047 : : loops don't and so are immediately lowered. */
4048 : :
4049 : : static void
4050 : 1958 : omp_apply_tile (tree for_stmt, tree sizes, int size)
4051 : : {
4052 : 1958 : tree pre_body = NULL_TREE, post_body = NULL_TREE;
4053 : 1958 : tree orig_sizes = sizes;
4054 : 1958 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
4055 : : {
4056 : 51 : error_at (EXPR_LOCATION (for_stmt), "non-rectangular %<tile%>");
4057 : 51 : return;
4058 : : }
4059 : 4434 : for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
4060 : : {
4061 : 2527 : if (orig_sizes)
4062 : : {
4063 : 1734 : size = tree_to_uhwi (TREE_VALUE (sizes));
4064 : 1734 : sizes = TREE_CHAIN (sizes);
4065 : : }
4066 : 2527 : if (size == 1)
4067 : 428 : continue;
4068 : 2099 : if (OMP_FOR_ORIG_DECLS (for_stmt) == NULL_TREE)
4069 : : {
4070 : 522 : OMP_FOR_ORIG_DECLS (for_stmt)
4071 : 522 : = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)));
4072 : 1188 : for (int j = 0; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
4073 : : {
4074 : 666 : gcc_assert (TREE_CODE (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j))
4075 : : == MODIFY_EXPR);
4076 : 666 : TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), j)
4077 : 1332 : = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j), 0);
4078 : : }
4079 : : }
4080 : 2099 : tree step;
4081 : 2099 : tree iters = omp_loop_number_of_iterations (for_stmt, i, &step);
4082 : 2099 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
4083 : 2099 : tree decl = TREE_OPERAND (t, 0);
4084 : 2099 : tree type = TREE_TYPE (decl);
4085 : 2099 : tree griddecl = create_tmp_var_raw (type);
4086 : 2099 : DECL_CONTEXT (griddecl) = current_function_decl;
4087 : 2099 : t = build1 (DECL_EXPR, void_type_node, griddecl);
4088 : 2099 : append_to_statement_list (t, &OMP_FOR_PRE_BODY (for_stmt));
4089 : 2099 : TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i), 0) = griddecl;
4090 : 2099 : TREE_PRIVATE (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i)) = 1;
4091 : 2099 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
4092 : 2099 : TREE_OPERAND (cond, 0) = griddecl;
4093 : 2099 : tree ub = save_expr (TREE_OPERAND (cond, 1));
4094 : 2099 : TREE_OPERAND (cond, 1) = ub;
4095 : 2099 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
4096 : 2099 : if (TREE_CODE (cond) == NE_EXPR)
4097 : : {
4098 : 163 : tree_code cond_code = TREE_CODE (cond);
4099 : 163 : omp_adjust_for_condition (EXPR_LOCATION (for_stmt), &cond_code,
4100 : : &ub, griddecl, step);
4101 : 163 : TREE_SET_CODE (cond, cond_code);
4102 : : }
4103 : 2099 : step = save_expr (step);
4104 : 2099 : tree gridstep = fold_build2 (MULT_EXPR, TREE_TYPE (step),
4105 : : step, build_int_cst (TREE_TYPE (step),
4106 : : size));
4107 : 2099 : if (POINTER_TYPE_P (type))
4108 : 52 : t = build2 (POINTER_PLUS_EXPR, type, griddecl,
4109 : : fold_convert (sizetype, gridstep));
4110 : : else
4111 : 2047 : t = build2 (PLUS_EXPR, type, griddecl, gridstep);
4112 : 2099 : t = build2 (MODIFY_EXPR, type, griddecl, t);
4113 : 2099 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
4114 : 2099 : t = build2 (MODIFY_EXPR, type, decl, griddecl);
4115 : 2099 : append_to_statement_list (t, &pre_body);
4116 : 2099 : if (POINTER_TYPE_P (type))
4117 : 52 : t = build2 (POINTER_PLUS_EXPR, type, griddecl,
4118 : : fold_convert (sizetype, gridstep));
4119 : : else
4120 : 2047 : t = build2 (PLUS_EXPR, type, griddecl, gridstep);
4121 : 2099 : bool minmax_needed = true;
4122 : 2099 : if (TREE_CODE (iters) == INTEGER_CST)
4123 : : {
4124 : 1135 : wide_int witers = wi::to_wide (iters);
4125 : 1135 : wide_int wsize = wide_int::from (size, witers.get_precision (),
4126 : 1135 : TYPE_SIGN (TREE_TYPE (iters)));
4127 : 1135 : if (wi::multiple_of_p (witers, wsize, TYPE_SIGN (TREE_TYPE (iters))))
4128 : 417 : minmax_needed = false;
4129 : 1135 : }
4130 : 1135 : if (minmax_needed)
4131 : 1682 : switch (TREE_CODE (cond))
4132 : : {
4133 : 251 : case LE_EXPR:
4134 : 251 : if (POINTER_TYPE_P (type))
4135 : 4 : t = build2 (MIN_EXPR, type, t,
4136 : 4 : build2 (POINTER_PLUS_EXPR, type, ub, size_int (1)));
4137 : : else
4138 : 247 : t = build2 (MIN_EXPR, type, t,
4139 : : build2 (PLUS_EXPR, type, ub, build_one_cst (type)));
4140 : : break;
4141 : 1375 : case LT_EXPR:
4142 : 1375 : t = build2 (MIN_EXPR, type, t, ub);
4143 : 1375 : break;
4144 : 28 : case GE_EXPR:
4145 : 28 : if (POINTER_TYPE_P (type))
4146 : 8 : t = build2 (MAX_EXPR, type, t,
4147 : 8 : build2 (POINTER_PLUS_EXPR, type, ub, size_int (-1)));
4148 : : else
4149 : 20 : t = build2 (MAX_EXPR, type, t,
4150 : : build2 (PLUS_EXPR, type, ub,
4151 : : build_minus_one_cst (type)));
4152 : : break;
4153 : 28 : case GT_EXPR:
4154 : 28 : t = build2 (MAX_EXPR, type, t, ub);
4155 : 28 : break;
4156 : 0 : default:
4157 : 0 : gcc_unreachable ();
4158 : : }
4159 : 2099 : tree end = create_tmp_var_raw (type);
4160 : 2099 : DECL_CONTEXT (end) = current_function_decl;
4161 : 2099 : end = build4 (TARGET_EXPR, type, end, t, NULL_TREE, NULL_TREE);
4162 : 2099 : TREE_SIDE_EFFECTS (end) = 1;
4163 : 2099 : append_to_statement_list (end, &pre_body);
4164 : 2099 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
4165 : 2099 : tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
4166 : 2099 : t = build1 (GOTO_EXPR, void_type_node, lab2);
4167 : 2099 : append_to_statement_list (t, &pre_body);
4168 : 2099 : t = build1 (LABEL_EXPR, void_type_node, lab1);
4169 : 2099 : append_to_statement_list (t, &pre_body);
4170 : 2099 : tree this_post_body = NULL_TREE;
4171 : 2099 : if (POINTER_TYPE_P (type))
4172 : 52 : t = build2 (POINTER_PLUS_EXPR, type, decl,
4173 : : fold_convert (sizetype, step));
4174 : : else
4175 : 2047 : t = build2 (PLUS_EXPR, type, decl, step);
4176 : 2099 : t = build2 (MODIFY_EXPR, type, decl, t);
4177 : 2099 : append_to_statement_list (t, &this_post_body);
4178 : 2099 : t = build1 (LABEL_EXPR, void_type_node, lab2);
4179 : 2099 : append_to_statement_list (t, &this_post_body);
4180 : 2165 : t = build2 ((TREE_CODE (cond) == LT_EXPR || TREE_CODE (cond) == LE_EXPR)
4181 : : ? LT_EXPR : GT_EXPR, boolean_type_node, decl, end);
4182 : 2099 : if (orig_sizes == NULL_TREE)
4183 : : {
4184 : 745 : gcc_assert (i == 0);
4185 : 745 : t = build3 (ANNOTATE_EXPR, TREE_TYPE (t), t,
4186 : : build_int_cst (integer_type_node,
4187 : 745 : annot_expr_unroll_kind),
4188 : : build_int_cst (integer_type_node, size));
4189 : : }
4190 : 2099 : t = build3 (COND_EXPR, void_type_node, t,
4191 : : build1 (GOTO_EXPR, void_type_node, lab1), NULL_TREE);
4192 : 2099 : append_to_statement_list (t, &this_post_body);
4193 : 2099 : append_to_statement_list (post_body, &this_post_body);
4194 : 2099 : post_body = this_post_body;
4195 : : }
4196 : 1907 : if (pre_body || post_body)
4197 : : {
4198 : 1614 : append_to_statement_list (OMP_FOR_BODY (for_stmt), &pre_body);
4199 : 1614 : append_to_statement_list (post_body, &pre_body);
4200 : 1614 : OMP_FOR_BODY (for_stmt) = pre_body;
4201 : : }
4202 : : }
4203 : :
4204 : : /* Callback for walk_tree to find nested loop transforming construct. */
4205 : :
4206 : : static tree
4207 : 9261 : find_nested_loop_xform (tree *tp, int *walk_subtrees, void *data)
4208 : : {
4209 : 9261 : tree **pdata = (tree **) data;
4210 : 9261 : *walk_subtrees = 0;
4211 : 9261 : switch (TREE_CODE (*tp))
4212 : : {
4213 : 1987 : case OMP_TILE:
4214 : 1987 : case OMP_UNROLL:
4215 : 1987 : pdata[1] = tp;
4216 : 1987 : return *tp;
4217 : 2581 : case BIND_EXPR:
4218 : 2581 : if (BIND_EXPR_VARS (*tp)
4219 : 2581 : || (BIND_EXPR_BLOCK (*tp)
4220 : 1270 : && BLOCK_VARS (BIND_EXPR_BLOCK (*tp))))
4221 : 1311 : pdata[0] = tp;
4222 : 2581 : *walk_subtrees = 1;
4223 : 2581 : break;
4224 : 425 : case STATEMENT_LIST:
4225 : 425 : if (!tsi_one_before_end_p (tsi_start (*tp)))
4226 : 425 : pdata[0] = tp;
4227 : 425 : *walk_subtrees = 1;
4228 : 425 : break;
4229 : 36 : case TRY_FINALLY_EXPR:
4230 : 36 : case CLEANUP_POINT_EXPR:
4231 : 36 : pdata[0] = tp;
4232 : 36 : *walk_subtrees = 1;
4233 : 36 : break;
4234 : : default:
4235 : : break;
4236 : : }
4237 : : return NULL;
4238 : : }
4239 : :
4240 : : /* Main entry point for performing OpenMP loop transformations. */
4241 : :
4242 : : void
4243 : 58471 : omp_maybe_apply_loop_xforms (tree *expr_p, tree for_clauses)
4244 : : {
4245 : 58471 : tree for_stmt = *expr_p;
4246 : :
4247 : 58471 : switch (TREE_CODE (for_stmt))
4248 : : {
4249 : 3923 : case OMP_TILE:
4250 : 3923 : case OMP_UNROLL:
4251 : 3923 : if (OMP_LOOPXFORM_LOWERED (for_stmt))
4252 : : return;
4253 : : break;
4254 : : default:
4255 : : break;
4256 : : }
4257 : :
4258 : : tree *inner_expr_p = expr_p;
4259 : : tree inner_for_stmt = for_stmt;
4260 : 138690 : for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
4261 : : {
4262 : : /* If some loop nest needs one or more loops in canonical form
4263 : : from nested loop transforming constructs, first perform the
4264 : : loop transformation on the nested construct and then move over
4265 : : the corresponding loops in canonical form from the inner construct
4266 : : to the outer one. */
4267 : 81941 : if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i) == NULL_TREE)
4268 : : {
4269 : 1516 : if (inner_for_stmt == for_stmt
4270 : 3008 : && omp_find_clause (for_clauses ? for_clauses
4271 : 1492 : : OMP_FOR_CLAUSES (for_stmt),
4272 : : OMP_CLAUSE_ORDERED))
4273 : : {
4274 : 73 : error_at (EXPR_LOCATION (for_stmt),
4275 : : "%<ordered%> clause used with generated loops");
4276 : 73 : *expr_p = void_node;
4277 : 73 : return;
4278 : : }
4279 : 1443 : tree *data[2] = { NULL, NULL };
4280 : 1443 : walk_tree (&OMP_FOR_BODY (inner_for_stmt),
4281 : : find_nested_loop_xform, &data, NULL);
4282 : 1443 : gcc_assert (data[1]);
4283 : 1443 : if (data[0])
4284 : : {
4285 : : /* If there is a BIND_EXPR declaring some vars, or statement
4286 : : list with more than one stmt etc., move the intervening
4287 : : code around the outermost loop. */
4288 : 1008 : tree t = *inner_expr_p;
4289 : 1008 : *inner_expr_p = OMP_FOR_BODY (inner_for_stmt);
4290 : 1008 : OMP_FOR_BODY (inner_for_stmt) = *data[1];
4291 : 1008 : *data[1] = t;
4292 : 1008 : inner_expr_p = data[1];
4293 : 1008 : data[1] = &OMP_FOR_BODY (inner_for_stmt);
4294 : : }
4295 : 1443 : inner_for_stmt = *data[1];
4296 : :
4297 : 1443 : omp_maybe_apply_loop_xforms (data[1], NULL_TREE);
4298 : 1443 : if (*data[1] != inner_for_stmt)
4299 : : {
4300 : 544 : tree *data2[2] = { NULL, NULL };
4301 : 544 : walk_tree (data[1], find_nested_loop_xform, &data2, NULL);
4302 : 544 : gcc_assert (data2[1]
4303 : : && *data2[1] == inner_for_stmt
4304 : : && data2[0]);
4305 : 544 : tree t = *inner_expr_p;
4306 : 544 : *inner_expr_p = *data[1];
4307 : 544 : *data[1] = *data2[1];
4308 : 544 : *data2[1] = t;
4309 : 544 : inner_expr_p = data2[1];
4310 : : }
4311 : 1443 : tree clauses = OMP_FOR_CLAUSES (inner_for_stmt);
4312 : 1443 : gcc_checking_assert (TREE_CODE (inner_for_stmt) != OMP_UNROLL
4313 : : || omp_find_clause (clauses,
4314 : : OMP_CLAUSE_PARTIAL));
4315 : 1443 : append_to_statement_list (OMP_FOR_PRE_BODY (inner_for_stmt),
4316 : : &OMP_FOR_PRE_BODY (for_stmt));
4317 : 1443 : OMP_FOR_PRE_BODY (inner_for_stmt) = NULL_TREE;
4318 : 1443 : if (OMP_FOR_ORIG_DECLS (for_stmt) == NULL_TREE
4319 : 1443 : && OMP_FOR_ORIG_DECLS (inner_for_stmt) != NULL_TREE)
4320 : : {
4321 : 624 : OMP_FOR_ORIG_DECLS (for_stmt)
4322 : 624 : = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)));
4323 : 1466 : for (int j = 0; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
4324 : : j++)
4325 : : {
4326 : 842 : if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j) == NULL_TREE)
4327 : 717 : continue;
4328 : 125 : gcc_assert (TREE_CODE (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt),
4329 : : j)) == MODIFY_EXPR);
4330 : 125 : TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), j)
4331 : 250 : = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j),
4332 : : 0);
4333 : : }
4334 : : }
4335 : 3104 : for (int j = 0; j < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt));
4336 : : ++j)
4337 : : {
4338 : 1924 : if (i + j == TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)))
4339 : : break;
4340 : 1661 : if (OMP_FOR_ORIG_DECLS (for_stmt))
4341 : : {
4342 : 1576 : if (OMP_FOR_ORIG_DECLS (inner_for_stmt))
4343 : : {
4344 : 1576 : TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i + j)
4345 : 1576 : = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
4346 : : j);
4347 : 1576 : TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), j)
4348 : 1576 : = NULL_TREE;
4349 : : }
4350 : : else
4351 : : {
4352 : 0 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (inner_for_stmt), j);
4353 : 0 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
4354 : 0 : TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i + j)
4355 : 0 : = TREE_OPERAND (t, 0);
4356 : : }
4357 : : }
4358 : 1661 : TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i + j)
4359 : 1661 : = TREE_VEC_ELT (OMP_FOR_INIT (inner_for_stmt), j);
4360 : 1661 : TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i + j)
4361 : 1661 : = TREE_VEC_ELT (OMP_FOR_COND (inner_for_stmt), j);
4362 : 1661 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i + j)
4363 : 1661 : = TREE_VEC_ELT (OMP_FOR_INCR (inner_for_stmt), j);
4364 : 1661 : TREE_VEC_ELT (OMP_FOR_INIT (inner_for_stmt), j) = NULL_TREE;
4365 : 1661 : TREE_VEC_ELT (OMP_FOR_COND (inner_for_stmt), j) = NULL_TREE;
4366 : 1661 : TREE_VEC_ELT (OMP_FOR_INCR (inner_for_stmt), j) = NULL_TREE;
4367 : : }
4368 : : }
4369 : : }
4370 : :
4371 : 56749 : switch (TREE_CODE (for_stmt))
4372 : : {
4373 : 1165 : case OMP_TILE:
4374 : 1165 : tree sizes;
4375 : 1165 : sizes = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_SIZES);
4376 : 1165 : omp_apply_tile (for_stmt, OMP_CLAUSE_SIZES_LIST (sizes), 0);
4377 : 1165 : OMP_LOOPXFORM_LOWERED (for_stmt) = 1;
4378 : 1165 : break;
4379 : 1109 : case OMP_UNROLL:
4380 : 1109 : tree partial;
4381 : 1109 : partial = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
4382 : : OMP_CLAUSE_PARTIAL);
4383 : 1109 : if (partial)
4384 : 793 : omp_apply_tile (for_stmt, NULL_TREE,
4385 : 793 : OMP_CLAUSE_PARTIAL_EXPR (partial)
4386 : 609 : ? tree_to_shwi (OMP_CLAUSE_PARTIAL_EXPR (partial))
4387 : : : 8);
4388 : 316 : else if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_FULL))
4389 : : {
4390 : 274 : tree iters = omp_loop_number_of_iterations (for_stmt, 0, NULL);
4391 : 274 : if (TREE_CODE (iters) != INTEGER_CST)
4392 : 12 : error_at (EXPR_LOCATION (for_stmt),
4393 : : "non-constant iteration count of %<unroll full%> loop");
4394 : : }
4395 : 1109 : OMP_LOOPXFORM_LOWERED (for_stmt) = 1;
4396 : 1109 : break;
4397 : : default:
4398 : : break;
4399 : : }
4400 : : }
4401 : :
4402 : : #include "gt-omp-general.h"
|