]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-general.c
gimplify.c (gimplify_scan_omp_clauses): For inscan reductions on worksharing loop...
[thirdparty/gcc.git] / gcc / omp-general.c
CommitLineData
629b3d75
MJ
1/* General types and functions that are uselful for processing of OpenMP,
2 OpenACC and similar directivers at various stages of compilation.
3
a5544970 4 Copyright (C) 2005-2019 Free Software Foundation, Inc.
629b3d75
MJ
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22/* Find an OMP clause of type KIND within CLAUSES. */
23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "backend.h"
28#include "target.h"
29#include "tree.h"
30#include "gimple.h"
31#include "ssa.h"
32#include "diagnostic-core.h"
33#include "fold-const.h"
34#include "langhooks.h"
35#include "omp-general.h"
314e6352
ML
36#include "stringpool.h"
37#include "attribs.h"
629b3d75 38
28567c40
JJ
39enum omp_requires omp_requires_mask;
40
629b3d75
MJ
41tree
42omp_find_clause (tree clauses, enum omp_clause_code kind)
43{
44 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
45 if (OMP_CLAUSE_CODE (clauses) == kind)
46 return clauses;
47
48 return NULL_TREE;
49}
50
51/* Return true if DECL is a reference type. */
52
53bool
54omp_is_reference (tree decl)
55{
56 return lang_hooks.decls.omp_privatize_by_reference (decl);
57}
58
031c5c8b
MJ
59/* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or GT_EXPR,
60 given that V is the loop index variable and STEP is loop step. */
629b3d75
MJ
61
62void
031c5c8b
MJ
63omp_adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2,
64 tree v, tree step)
629b3d75
MJ
65{
66 switch (*cond_code)
67 {
68 case LT_EXPR:
69 case GT_EXPR:
031c5c8b
MJ
70 break;
71
629b3d75 72 case NE_EXPR:
031c5c8b
MJ
73 gcc_assert (TREE_CODE (step) == INTEGER_CST);
74 if (TREE_CODE (TREE_TYPE (v)) == INTEGER_TYPE)
75 {
76 if (integer_onep (step))
77 *cond_code = LT_EXPR;
78 else
79 {
80 gcc_assert (integer_minus_onep (step));
81 *cond_code = GT_EXPR;
82 }
83 }
84 else
85 {
86 tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v)));
87 gcc_assert (TREE_CODE (unit) == INTEGER_CST);
88 if (tree_int_cst_equal (unit, step))
89 *cond_code = LT_EXPR;
90 else
91 {
92 gcc_assert (wi::neg (wi::to_widest (unit))
93 == wi::to_widest (step));
94 *cond_code = GT_EXPR;
95 }
96 }
97
629b3d75 98 break;
031c5c8b 99
629b3d75
MJ
100 case LE_EXPR:
101 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
102 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
103 else
104 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
105 build_int_cst (TREE_TYPE (*n2), 1));
106 *cond_code = LT_EXPR;
107 break;
108 case GE_EXPR:
109 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
110 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
111 else
112 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
113 build_int_cst (TREE_TYPE (*n2), 1));
114 *cond_code = GT_EXPR;
115 break;
116 default:
117 gcc_unreachable ();
118 }
119}
120
121/* Return the looping step from INCR, extracted from the step of a gimple omp
122 for statement. */
123
124tree
125omp_get_for_step_from_incr (location_t loc, tree incr)
126{
127 tree step;
128 switch (TREE_CODE (incr))
129 {
130 case PLUS_EXPR:
131 step = TREE_OPERAND (incr, 1);
132 break;
133 case POINTER_PLUS_EXPR:
134 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
135 break;
136 case MINUS_EXPR:
137 step = TREE_OPERAND (incr, 1);
138 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
139 break;
140 default:
141 gcc_unreachable ();
142 }
143 return step;
144}
145
146/* Extract the header elements of parallel loop FOR_STMT and store
147 them into *FD. */
148
149void
150omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
151 struct omp_for_data_loop *loops)
152{
153 tree t, var, *collapse_iter, *collapse_count;
154 tree count = NULL_TREE, iter_type = long_integer_type_node;
155 struct omp_for_data_loop *loop;
156 int i;
157 struct omp_for_data_loop dummy_loop;
158 location_t loc = gimple_location (for_stmt);
159 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
160 bool distribute = gimple_omp_for_kind (for_stmt)
161 == GF_OMP_FOR_KIND_DISTRIBUTE;
162 bool taskloop = gimple_omp_for_kind (for_stmt)
163 == GF_OMP_FOR_KIND_TASKLOOP;
164 tree iterv, countv;
165
166 fd->for_stmt = for_stmt;
167 fd->pre = NULL;
629b3d75
MJ
168 fd->have_nowait = distribute || simd;
169 fd->have_ordered = false;
28567c40 170 fd->have_reductemp = false;
8221c30b 171 fd->have_pointer_condtemp = false;
6c7ae8c5 172 fd->lastprivate_conditional = 0;
02889d23 173 fd->tiling = NULL_TREE;
629b3d75
MJ
174 fd->collapse = 1;
175 fd->ordered = 0;
176 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
177 fd->sched_modifiers = 0;
178 fd->chunk_size = NULL_TREE;
179 fd->simd_schedule = false;
629b3d75
MJ
180 collapse_iter = NULL;
181 collapse_count = NULL;
182
183 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
184 switch (OMP_CLAUSE_CODE (t))
185 {
186 case OMP_CLAUSE_NOWAIT:
187 fd->have_nowait = true;
188 break;
189 case OMP_CLAUSE_ORDERED:
190 fd->have_ordered = true;
191 if (OMP_CLAUSE_ORDERED_EXPR (t))
192 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
193 break;
194 case OMP_CLAUSE_SCHEDULE:
195 gcc_assert (!distribute && !taskloop);
196 fd->sched_kind
197 = (enum omp_clause_schedule_kind)
198 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
199 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
200 & ~OMP_CLAUSE_SCHEDULE_MASK);
201 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
202 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
203 break;
204 case OMP_CLAUSE_DIST_SCHEDULE:
205 gcc_assert (distribute);
206 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
207 break;
208 case OMP_CLAUSE_COLLAPSE:
209 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
210 if (fd->collapse > 1)
211 {
212 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
213 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
214 }
215 break;
02889d23
CLT
216 case OMP_CLAUSE_TILE:
217 fd->tiling = OMP_CLAUSE_TILE_LIST (t);
218 fd->collapse = list_length (fd->tiling);
219 gcc_assert (fd->collapse);
220 collapse_iter = &OMP_CLAUSE_TILE_ITERVAR (t);
221 collapse_count = &OMP_CLAUSE_TILE_COUNT (t);
222 break;
28567c40
JJ
223 case OMP_CLAUSE__REDUCTEMP_:
224 fd->have_reductemp = true;
6c7ae8c5
JJ
225 break;
226 case OMP_CLAUSE_LASTPRIVATE:
227 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t))
228 fd->lastprivate_conditional++;
229 break;
8221c30b
JJ
230 case OMP_CLAUSE__CONDTEMP_:
231 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t))))
232 fd->have_pointer_condtemp = true;
233 break;
629b3d75
MJ
234 default:
235 break;
236 }
02889d23
CLT
237
238 if (fd->collapse > 1 || fd->tiling)
239 fd->loops = loops;
240 else
241 fd->loops = &fd->loop;
242
629b3d75
MJ
243 if (fd->ordered && fd->collapse == 1 && loops != NULL)
244 {
245 fd->loops = loops;
246 iterv = NULL_TREE;
247 countv = NULL_TREE;
248 collapse_iter = &iterv;
249 collapse_count = &countv;
250 }
251
252 /* FIXME: for now map schedule(auto) to schedule(static).
253 There should be analysis to determine whether all iterations
254 are approximately the same amount of work (then schedule(static)
255 is best) or if it varies (then schedule(dynamic,N) is better). */
256 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
257 {
258 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
259 gcc_assert (fd->chunk_size == NULL);
260 }
02889d23 261 gcc_assert ((fd->collapse == 1 && !fd->tiling) || collapse_iter != NULL);
629b3d75
MJ
262 if (taskloop)
263 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
264 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
265 gcc_assert (fd->chunk_size == NULL);
266 else if (fd->chunk_size == NULL)
267 {
268 /* We only need to compute a default chunk size for ordered
269 static loops and dynamic loops. */
270 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
271 || fd->have_ordered)
272 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
273 ? integer_zero_node : integer_one_node;
274 }
275
276 int cnt = fd->ordered ? fd->ordered : fd->collapse;
277 for (i = 0; i < cnt; i++)
278 {
02889d23
CLT
279 if (i == 0
280 && fd->collapse == 1
281 && !fd->tiling
282 && (fd->ordered == 0 || loops == NULL))
629b3d75
MJ
283 loop = &fd->loop;
284 else if (loops != NULL)
285 loop = loops + i;
286 else
287 loop = &dummy_loop;
288
289 loop->v = gimple_omp_for_index (for_stmt, i);
290 gcc_assert (SSA_VAR_P (loop->v));
291 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
292 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
293 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
294 loop->n1 = gimple_omp_for_initial (for_stmt, i);
295
296 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
297 loop->n2 = gimple_omp_for_final (for_stmt, i);
28567c40
JJ
298 gcc_assert (loop->cond_code != NE_EXPR
299 || (gimple_omp_for_kind (for_stmt)
300 != GF_OMP_FOR_KIND_OACC_LOOP));
629b3d75
MJ
301
302 t = gimple_omp_for_incr (for_stmt, i);
303 gcc_assert (TREE_OPERAND (t, 0) == var);
304 loop->step = omp_get_for_step_from_incr (loc, t);
305
031c5c8b
MJ
306 omp_adjust_for_condition (loc, &loop->cond_code, &loop->n2, loop->v,
307 loop->step);
28567c40 308
629b3d75
MJ
309 if (simd
310 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
311 && !fd->have_ordered))
312 {
02889d23 313 if (fd->collapse == 1 && !fd->tiling)
629b3d75
MJ
314 iter_type = TREE_TYPE (loop->v);
315 else if (i == 0
316 || TYPE_PRECISION (iter_type)
317 < TYPE_PRECISION (TREE_TYPE (loop->v)))
318 iter_type
319 = build_nonstandard_integer_type
320 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
321 }
322 else if (iter_type != long_long_unsigned_type_node)
323 {
324 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
325 iter_type = long_long_unsigned_type_node;
326 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
327 && TYPE_PRECISION (TREE_TYPE (loop->v))
328 >= TYPE_PRECISION (iter_type))
329 {
330 tree n;
331
332 if (loop->cond_code == LT_EXPR)
28567c40
JJ
333 n = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
334 loop->n2, loop->step);
629b3d75
MJ
335 else
336 n = loop->n1;
337 if (TREE_CODE (n) != INTEGER_CST
338 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
339 iter_type = long_long_unsigned_type_node;
340 }
341 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
342 > TYPE_PRECISION (iter_type))
343 {
344 tree n1, n2;
345
346 if (loop->cond_code == LT_EXPR)
347 {
348 n1 = loop->n1;
28567c40
JJ
349 n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
350 loop->n2, loop->step);
629b3d75
MJ
351 }
352 else
353 {
28567c40
JJ
354 n1 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (loop->v),
355 loop->n2, loop->step);
629b3d75
MJ
356 n2 = loop->n1;
357 }
358 if (TREE_CODE (n1) != INTEGER_CST
359 || TREE_CODE (n2) != INTEGER_CST
360 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
361 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
362 iter_type = long_long_unsigned_type_node;
363 }
364 }
365
366 if (i >= fd->collapse)
367 continue;
368
369 if (collapse_count && *collapse_count == NULL)
370 {
371 t = fold_binary (loop->cond_code, boolean_type_node,
372 fold_convert (TREE_TYPE (loop->v), loop->n1),
373 fold_convert (TREE_TYPE (loop->v), loop->n2));
374 if (t && integer_zerop (t))
375 count = build_zero_cst (long_long_unsigned_type_node);
376 else if ((i == 0 || count != NULL_TREE)
377 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
378 && TREE_CONSTANT (loop->n1)
379 && TREE_CONSTANT (loop->n2)
380 && TREE_CODE (loop->step) == INTEGER_CST)
381 {
382 tree itype = TREE_TYPE (loop->v);
383
384 if (POINTER_TYPE_P (itype))
385 itype = signed_type_for (itype);
386 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
28567c40
JJ
387 t = fold_build2_loc (loc, PLUS_EXPR, itype,
388 fold_convert_loc (loc, itype, loop->step),
389 t);
629b3d75 390 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
28567c40 391 fold_convert_loc (loc, itype, loop->n2));
629b3d75 392 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
28567c40 393 fold_convert_loc (loc, itype, loop->n1));
629b3d75 394 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
28567c40
JJ
395 {
396 tree step = fold_convert_loc (loc, itype, loop->step);
397 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
398 fold_build1_loc (loc, NEGATE_EXPR,
399 itype, t),
400 fold_build1_loc (loc, NEGATE_EXPR,
401 itype, step));
402 }
629b3d75
MJ
403 else
404 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
28567c40
JJ
405 fold_convert_loc (loc, itype,
406 loop->step));
629b3d75
MJ
407 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
408 if (count != NULL_TREE)
28567c40
JJ
409 count = fold_build2_loc (loc, MULT_EXPR,
410 long_long_unsigned_type_node,
411 count, t);
629b3d75
MJ
412 else
413 count = t;
414 if (TREE_CODE (count) != INTEGER_CST)
415 count = NULL_TREE;
416 }
417 else if (count && !integer_zerop (count))
418 count = NULL_TREE;
419 }
420 }
421
422 if (count
423 && !simd
424 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
425 || fd->have_ordered))
426 {
427 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
428 iter_type = long_long_unsigned_type_node;
429 else
430 iter_type = long_integer_type_node;
431 }
432 else if (collapse_iter && *collapse_iter != NULL)
433 iter_type = TREE_TYPE (*collapse_iter);
434 fd->iter_type = iter_type;
435 if (collapse_iter && *collapse_iter == NULL)
436 *collapse_iter = create_tmp_var (iter_type, ".iter");
437 if (collapse_count && *collapse_count == NULL)
438 {
439 if (count)
440 *collapse_count = fold_convert_loc (loc, iter_type, count);
441 else
442 *collapse_count = create_tmp_var (iter_type, ".count");
443 }
444
02889d23 445 if (fd->collapse > 1 || fd->tiling || (fd->ordered && loops))
629b3d75
MJ
446 {
447 fd->loop.v = *collapse_iter;
448 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
449 fd->loop.n2 = *collapse_count;
450 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
451 fd->loop.cond_code = LT_EXPR;
452 }
453 else if (loops)
454 loops[0] = fd->loop;
455}
456
457/* Build a call to GOMP_barrier. */
458
459gimple *
460omp_build_barrier (tree lhs)
461{
462 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
463 : BUILT_IN_GOMP_BARRIER);
464 gcall *g = gimple_build_call (fndecl, 0);
465 if (lhs)
466 gimple_call_set_lhs (g, lhs);
467 return g;
468}
469
470/* Return maximum possible vectorization factor for the target. */
471
9d2f08ab 472poly_uint64
629b3d75
MJ
473omp_max_vf (void)
474{
475 if (!optimize
476 || optimize_debug
477 || !flag_tree_loop_optimize
478 || (!flag_tree_loop_vectorize
26d476cd 479 && global_options_set.x_flag_tree_loop_vectorize))
629b3d75
MJ
480 return 1;
481
86e36728 482 auto_vector_sizes sizes;
f63445e5 483 targetm.vectorize.autovectorize_vector_sizes (&sizes, true);
86e36728 484 if (!sizes.is_empty ())
629b3d75 485 {
86e36728
RS
486 poly_uint64 vf = 0;
487 for (unsigned int i = 0; i < sizes.length (); ++i)
488 vf = ordered_max (vf, sizes[i]);
489 return vf;
629b3d75 490 }
86e36728
RS
491
492 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
493 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
494 return GET_MODE_NUNITS (vqimode);
495
496 return 1;
629b3d75
MJ
497}
498
499/* Return maximum SIMT width if offloading may target SIMT hardware. */
500
501int
502omp_max_simt_vf (void)
503{
504 if (!optimize)
505 return 0;
506 if (ENABLE_OFFLOADING)
01914336 507 for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
629b3d75
MJ
508 {
509 if (!strncmp (c, "nvptx", strlen ("nvptx")))
510 return 32;
511 else if ((c = strchr (c, ',')))
512 c++;
513 }
514 return 0;
515}
516
517/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
518 macro on gomp-constants.h. We do not check for overflow. */
519
520tree
521oacc_launch_pack (unsigned code, tree device, unsigned op)
522{
523 tree res;
524
525 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
526 if (device)
527 {
528 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
529 device, build_int_cst (unsigned_type_node,
530 GOMP_LAUNCH_DEVICE_SHIFT));
531 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
532 }
533 return res;
534}
535
536/* FIXME: What is the following comment for? */
537/* Look for compute grid dimension clauses and convert to an attribute
538 attached to FN. This permits the target-side code to (a) massage
539 the dimensions, (b) emit that data and (c) optimize. Non-constant
540 dimensions are pushed onto ARGS.
541
542 The attribute value is a TREE_LIST. A set of dimensions is
543 represented as a list of INTEGER_CST. Those that are runtime
544 exprs are represented as an INTEGER_CST of zero.
545
01914336 546 TODO: Normally the attribute will just contain a single such list. If
629b3d75
MJ
547 however it contains a list of lists, this will represent the use of
548 device_type. Each member of the outer list is an assoc list of
549 dimensions, keyed by the device type. The first entry will be the
550 default. Well, that's the plan. */
551
552/* Replace any existing oacc fn attribute with updated dimensions. */
553
68034b1b
TS
554/* Variant working on a list of attributes. */
555
556tree
557oacc_replace_fn_attrib_attr (tree attribs, tree dims)
629b3d75
MJ
558{
559 tree ident = get_identifier (OACC_FN_ATTRIB);
629b3d75
MJ
560
561 /* If we happen to be present as the first attrib, drop it. */
562 if (attribs && TREE_PURPOSE (attribs) == ident)
563 attribs = TREE_CHAIN (attribs);
68034b1b
TS
564 return tree_cons (ident, dims, attribs);
565}
566
567/* Variant working on a function decl. */
568
569void
570oacc_replace_fn_attrib (tree fn, tree dims)
571{
572 DECL_ATTRIBUTES (fn)
573 = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn), dims);
629b3d75
MJ
574}
575
576/* Scan CLAUSES for launch dimensions and attach them to the oacc
577 function attribute. Push any that are non-constant onto the ARGS
25651634 578 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
629b3d75
MJ
579
580void
25651634 581oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args)
629b3d75
MJ
582{
583 /* Must match GOMP_DIM ordering. */
584 static const omp_clause_code ids[]
585 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
586 OMP_CLAUSE_VECTOR_LENGTH };
587 unsigned ix;
588 tree dims[GOMP_DIM_MAX];
589
590 tree attr = NULL_TREE;
591 unsigned non_const = 0;
592
593 for (ix = GOMP_DIM_MAX; ix--;)
594 {
595 tree clause = omp_find_clause (clauses, ids[ix]);
596 tree dim = NULL_TREE;
597
598 if (clause)
599 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
600 dims[ix] = dim;
601 if (dim && TREE_CODE (dim) != INTEGER_CST)
602 {
603 dim = integer_zero_node;
604 non_const |= GOMP_DIM_MASK (ix);
605 }
606 attr = tree_cons (NULL_TREE, dim, attr);
629b3d75
MJ
607 }
608
609 oacc_replace_fn_attrib (fn, attr);
610
611 if (non_const)
612 {
613 /* Push a dynamic argument set. */
614 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
615 NULL_TREE, non_const));
616 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
617 if (non_const & GOMP_DIM_MASK (ix))
618 args->safe_push (dims[ix]);
619 }
620}
621
5bf04509
TS
622/* Verify OpenACC routine clauses.
623
b48f44bf
TS
624 Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
625 if it has already been marked in compatible way, and -1 if incompatible.
5bf04509
TS
626 Upon returning, the chain of clauses will contain exactly one clause
627 specifying the level of parallelism. */
628
b48f44bf
TS
629int
630oacc_verify_routine_clauses (tree fndecl, tree *clauses, location_t loc,
631 const char *routine_str)
5bf04509
TS
632{
633 tree c_level = NULL_TREE;
634 tree c_p = NULL_TREE;
635 for (tree c = *clauses; c; c_p = c, c = OMP_CLAUSE_CHAIN (c))
636 switch (OMP_CLAUSE_CODE (c))
637 {
638 case OMP_CLAUSE_GANG:
639 case OMP_CLAUSE_WORKER:
640 case OMP_CLAUSE_VECTOR:
641 case OMP_CLAUSE_SEQ:
642 if (c_level == NULL_TREE)
643 c_level = c;
644 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_CODE (c_level))
645 {
646 /* This has already been diagnosed in the front ends. */
647 /* Drop the duplicate clause. */
648 gcc_checking_assert (c_p != NULL_TREE);
649 OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
650 c = c_p;
651 }
652 else
653 {
654 error_at (OMP_CLAUSE_LOCATION (c),
655 "%qs specifies a conflicting level of parallelism",
656 omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
657 inform (OMP_CLAUSE_LOCATION (c_level),
658 "... to the previous %qs clause here",
659 omp_clause_code_name[OMP_CLAUSE_CODE (c_level)]);
660 /* Drop the conflicting clause. */
661 gcc_checking_assert (c_p != NULL_TREE);
662 OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
663 c = c_p;
664 }
665 break;
666 default:
667 gcc_unreachable ();
668 }
669 if (c_level == NULL_TREE)
670 {
671 /* Default to an implicit 'seq' clause. */
672 c_level = build_omp_clause (loc, OMP_CLAUSE_SEQ);
673 OMP_CLAUSE_CHAIN (c_level) = *clauses;
674 *clauses = c_level;
675 }
b48f44bf
TS
676 /* In *clauses, we now have exactly one clause specifying the level of
677 parallelism. */
678
679 tree attr
680 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl));
681 if (attr != NULL_TREE)
682 {
683 /* If a "#pragma acc routine" has already been applied, just verify
684 this one for compatibility. */
685 /* Collect previous directive's clauses. */
686 tree c_level_p = NULL_TREE;
687 for (tree c = TREE_VALUE (attr); c; c = OMP_CLAUSE_CHAIN (c))
688 switch (OMP_CLAUSE_CODE (c))
689 {
690 case OMP_CLAUSE_GANG:
691 case OMP_CLAUSE_WORKER:
692 case OMP_CLAUSE_VECTOR:
693 case OMP_CLAUSE_SEQ:
694 gcc_checking_assert (c_level_p == NULL_TREE);
695 c_level_p = c;
696 break;
697 default:
698 gcc_unreachable ();
699 }
700 gcc_checking_assert (c_level_p != NULL_TREE);
701 /* ..., and compare to current directive's, which we've already collected
702 above. */
703 tree c_diag;
704 tree c_diag_p;
705 /* Matching level of parallelism? */
706 if (OMP_CLAUSE_CODE (c_level) != OMP_CLAUSE_CODE (c_level_p))
707 {
708 c_diag = c_level;
709 c_diag_p = c_level_p;
710 goto incompatible;
711 }
712 /* Compatible. */
713 return 1;
714
715 incompatible:
716 if (c_diag != NULL_TREE)
717 error_at (OMP_CLAUSE_LOCATION (c_diag),
718 "incompatible %qs clause when applying"
719 " %<%s%> to %qD, which has already been"
720 " marked with an OpenACC 'routine' directive",
721 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)],
722 routine_str, fndecl);
723 else if (c_diag_p != NULL_TREE)
724 error_at (loc,
725 "missing %qs clause when applying"
726 " %<%s%> to %qD, which has already been"
727 " marked with an OpenACC 'routine' directive",
728 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)],
729 routine_str, fndecl);
730 else
731 gcc_unreachable ();
732 if (c_diag_p != NULL_TREE)
733 inform (OMP_CLAUSE_LOCATION (c_diag_p),
734 "... with %qs clause here",
735 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)]);
736 else
737 {
738 /* In the front ends, we don't preserve location information for the
739 OpenACC routine directive itself. However, that of c_level_p
740 should be close. */
741 location_t loc_routine = OMP_CLAUSE_LOCATION (c_level_p);
742 inform (loc_routine, "... without %qs clause near to here",
743 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)]);
744 }
745 /* Incompatible. */
746 return -1;
747 }
748
749 return 0;
5bf04509
TS
750}
751
752/* Process the OpenACC 'routine' directive clauses to generate an attribute
753 for the level of parallelism. All dimensions have a size of zero
629b3d75
MJ
754 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
755 can have a loop partitioned on it. non-zero indicates
756 yes, zero indicates no. By construction once a non-zero has been
757 reached, further inner dimensions must also be non-zero. We set
758 TREE_VALUE to zero for the dimensions that may be partitioned and
759 1 for the other ones -- if a loop is (erroneously) spawned at
760 an outer level, we don't want to try and partition it. */
761
762tree
763oacc_build_routine_dims (tree clauses)
764{
765 /* Must match GOMP_DIM ordering. */
01914336
MJ
766 static const omp_clause_code ids[]
767 = {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
629b3d75
MJ
768 int ix;
769 int level = -1;
770
771 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
772 for (ix = GOMP_DIM_MAX + 1; ix--;)
773 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
774 {
629b3d75
MJ
775 level = ix;
776 break;
777 }
5bf04509 778 gcc_checking_assert (level >= 0);
629b3d75
MJ
779
780 tree dims = NULL_TREE;
781
782 for (ix = GOMP_DIM_MAX; ix--;)
783 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
784 build_int_cst (integer_type_node, ix < level), dims);
785
786 return dims;
787}
788
789/* Retrieve the oacc function attrib and return it. Non-oacc
790 functions will return NULL. */
791
792tree
793oacc_get_fn_attrib (tree fn)
794{
795 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
796}
797
46dbeb40
TV
798/* Return true if FN is an OpenMP or OpenACC offloading function. */
799
800bool
801offloading_function_p (tree fn)
802{
803 tree attrs = DECL_ATTRIBUTES (fn);
804 return (lookup_attribute ("omp declare target", attrs)
805 || lookup_attribute ("omp target entrypoint", attrs));
806}
807
629b3d75
MJ
808/* Extract an oacc execution dimension from FN. FN must be an
809 offloaded function or routine that has already had its execution
810 dimensions lowered to the target-specific values. */
811
812int
813oacc_get_fn_dim_size (tree fn, int axis)
814{
815 tree attrs = oacc_get_fn_attrib (fn);
816
817 gcc_assert (axis < GOMP_DIM_MAX);
818
819 tree dims = TREE_VALUE (attrs);
820 while (axis--)
821 dims = TREE_CHAIN (dims);
822
823 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
824
825 return size;
826}
827
828/* Extract the dimension axis from an IFN_GOACC_DIM_POS or
829 IFN_GOACC_DIM_SIZE call. */
830
831int
832oacc_get_ifn_dim_arg (const gimple *stmt)
833{
834 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
835 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
836 tree arg = gimple_call_arg (stmt, 0);
837 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
838
839 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
840 return (int) axis;
841}