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