1 /* General types and functions that are uselful for processing of OpenMP,
2 OpenACC and similar directivers at various stages of compilation.
4 Copyright (C) 2005-2019 Free Software Foundation, Inc.
6 This file is part of GCC.
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
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
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/>. */
22 /* Find an OMP clause of type KIND within CLAUSES. */
26 #include "coretypes.h"
32 #include "diagnostic-core.h"
33 #include "fold-const.h"
34 #include "langhooks.h"
35 #include "omp-general.h"
36 #include "stringpool.h"
39 enum omp_requires omp_requires_mask
;
42 omp_find_clause (tree clauses
, enum omp_clause_code kind
)
44 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
45 if (OMP_CLAUSE_CODE (clauses
) == kind
)
51 /* Return true if DECL is a reference type. */
54 omp_is_reference (tree decl
)
56 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
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. */
63 omp_adjust_for_condition (location_t loc
, enum tree_code
*cond_code
, tree
*n2
,
73 gcc_assert (TREE_CODE (step
) == INTEGER_CST
);
74 if (TREE_CODE (TREE_TYPE (v
)) == INTEGER_TYPE
)
76 if (integer_onep (step
))
80 gcc_assert (integer_minus_onep (step
));
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
))
92 gcc_assert (wi::neg (wi::to_widest (unit
))
93 == wi::to_widest (step
));
101 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
102 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, 1);
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
;
109 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
110 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, -1);
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
;
121 /* Return the looping step from INCR, extracted from the step of a gimple omp
125 omp_get_for_step_from_incr (location_t loc
, tree incr
)
128 switch (TREE_CODE (incr
))
131 step
= TREE_OPERAND (incr
, 1);
133 case POINTER_PLUS_EXPR
:
134 step
= fold_convert (ssizetype
, TREE_OPERAND (incr
, 1));
137 step
= TREE_OPERAND (incr
, 1);
138 step
= fold_build1_loc (loc
, NEGATE_EXPR
, TREE_TYPE (step
), step
);
146 /* Extract the header elements of parallel loop FOR_STMT and store
150 omp_extract_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
151 struct omp_for_data_loop
*loops
)
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
;
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
;
166 fd
->for_stmt
= for_stmt
;
168 fd
->have_nowait
= distribute
|| simd
;
169 fd
->have_ordered
= false;
170 fd
->have_reductemp
= false;
171 fd
->have_pointer_condtemp
= false;
172 fd
->have_scantemp
= false;
173 fd
->have_nonctrl_scantemp
= false;
174 fd
->lastprivate_conditional
= 0;
175 fd
->tiling
= NULL_TREE
;
178 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
179 fd
->sched_modifiers
= 0;
180 fd
->chunk_size
= NULL_TREE
;
181 fd
->simd_schedule
= false;
182 collapse_iter
= NULL
;
183 collapse_count
= NULL
;
185 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
186 switch (OMP_CLAUSE_CODE (t
))
188 case OMP_CLAUSE_NOWAIT
:
189 fd
->have_nowait
= true;
191 case OMP_CLAUSE_ORDERED
:
192 fd
->have_ordered
= true;
193 if (OMP_CLAUSE_ORDERED_EXPR (t
))
194 fd
->ordered
= tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t
));
196 case OMP_CLAUSE_SCHEDULE
:
197 gcc_assert (!distribute
&& !taskloop
);
199 = (enum omp_clause_schedule_kind
)
200 (OMP_CLAUSE_SCHEDULE_KIND (t
) & OMP_CLAUSE_SCHEDULE_MASK
);
201 fd
->sched_modifiers
= (OMP_CLAUSE_SCHEDULE_KIND (t
)
202 & ~OMP_CLAUSE_SCHEDULE_MASK
);
203 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
204 fd
->simd_schedule
= OMP_CLAUSE_SCHEDULE_SIMD (t
);
206 case OMP_CLAUSE_DIST_SCHEDULE
:
207 gcc_assert (distribute
);
208 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
210 case OMP_CLAUSE_COLLAPSE
:
211 fd
->collapse
= tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t
));
212 if (fd
->collapse
> 1)
214 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
215 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
218 case OMP_CLAUSE_TILE
:
219 fd
->tiling
= OMP_CLAUSE_TILE_LIST (t
);
220 fd
->collapse
= list_length (fd
->tiling
);
221 gcc_assert (fd
->collapse
);
222 collapse_iter
= &OMP_CLAUSE_TILE_ITERVAR (t
);
223 collapse_count
= &OMP_CLAUSE_TILE_COUNT (t
);
225 case OMP_CLAUSE__REDUCTEMP_
:
226 fd
->have_reductemp
= true;
228 case OMP_CLAUSE_LASTPRIVATE
:
229 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t
))
230 fd
->lastprivate_conditional
++;
232 case OMP_CLAUSE__CONDTEMP_
:
233 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t
))))
234 fd
->have_pointer_condtemp
= true;
236 case OMP_CLAUSE__SCANTEMP_
:
237 fd
->have_scantemp
= true;
238 if (!OMP_CLAUSE__SCANTEMP__ALLOC (t
)
239 && !OMP_CLAUSE__SCANTEMP__CONTROL (t
))
240 fd
->have_nonctrl_scantemp
= true;
246 if (fd
->collapse
> 1 || fd
->tiling
)
249 fd
->loops
= &fd
->loop
;
251 if (fd
->ordered
&& fd
->collapse
== 1 && loops
!= NULL
)
256 collapse_iter
= &iterv
;
257 collapse_count
= &countv
;
260 /* FIXME: for now map schedule(auto) to schedule(static).
261 There should be analysis to determine whether all iterations
262 are approximately the same amount of work (then schedule(static)
263 is best) or if it varies (then schedule(dynamic,N) is better). */
264 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
266 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
267 gcc_assert (fd
->chunk_size
== NULL
);
269 gcc_assert ((fd
->collapse
== 1 && !fd
->tiling
) || collapse_iter
!= NULL
);
271 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_RUNTIME
;
272 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
273 gcc_assert (fd
->chunk_size
== NULL
);
274 else if (fd
->chunk_size
== NULL
)
276 /* We only need to compute a default chunk size for ordered
277 static loops and dynamic loops. */
278 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
280 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
281 ? integer_zero_node
: integer_one_node
;
284 int cnt
= fd
->ordered
? fd
->ordered
: fd
->collapse
;
285 for (i
= 0; i
< cnt
; i
++)
290 && (fd
->ordered
== 0 || loops
== NULL
))
292 else if (loops
!= NULL
)
297 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
298 gcc_assert (SSA_VAR_P (loop
->v
));
299 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
300 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
301 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
302 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
304 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
305 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
306 gcc_assert (loop
->cond_code
!= NE_EXPR
307 || (gimple_omp_for_kind (for_stmt
)
308 != GF_OMP_FOR_KIND_OACC_LOOP
));
310 t
= gimple_omp_for_incr (for_stmt
, i
);
311 gcc_assert (TREE_OPERAND (t
, 0) == var
);
312 loop
->step
= omp_get_for_step_from_incr (loc
, t
);
314 omp_adjust_for_condition (loc
, &loop
->cond_code
, &loop
->n2
, loop
->v
,
318 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
319 && !fd
->have_ordered
))
321 if (fd
->collapse
== 1 && !fd
->tiling
)
322 iter_type
= TREE_TYPE (loop
->v
);
324 || TYPE_PRECISION (iter_type
)
325 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
327 = build_nonstandard_integer_type
328 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
330 else if (iter_type
!= long_long_unsigned_type_node
)
332 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
333 iter_type
= long_long_unsigned_type_node
;
334 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
335 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
336 >= TYPE_PRECISION (iter_type
))
340 if (loop
->cond_code
== LT_EXPR
)
341 n
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
342 loop
->n2
, loop
->step
);
345 if (TREE_CODE (n
) != INTEGER_CST
346 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
347 iter_type
= long_long_unsigned_type_node
;
349 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
350 > TYPE_PRECISION (iter_type
))
354 if (loop
->cond_code
== LT_EXPR
)
357 n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
358 loop
->n2
, loop
->step
);
362 n1
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (loop
->v
),
363 loop
->n2
, loop
->step
);
366 if (TREE_CODE (n1
) != INTEGER_CST
367 || TREE_CODE (n2
) != INTEGER_CST
368 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
369 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
370 iter_type
= long_long_unsigned_type_node
;
374 if (i
>= fd
->collapse
)
377 if (collapse_count
&& *collapse_count
== NULL
)
379 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
380 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
381 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
382 if (t
&& integer_zerop (t
))
383 count
= build_zero_cst (long_long_unsigned_type_node
);
384 else if ((i
== 0 || count
!= NULL_TREE
)
385 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
386 && TREE_CONSTANT (loop
->n1
)
387 && TREE_CONSTANT (loop
->n2
)
388 && TREE_CODE (loop
->step
) == INTEGER_CST
)
390 tree itype
= TREE_TYPE (loop
->v
);
392 if (POINTER_TYPE_P (itype
))
393 itype
= signed_type_for (itype
);
394 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
395 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
,
396 fold_convert_loc (loc
, itype
, loop
->step
),
398 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
399 fold_convert_loc (loc
, itype
, loop
->n2
));
400 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
401 fold_convert_loc (loc
, itype
, loop
->n1
));
402 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
404 tree step
= fold_convert_loc (loc
, itype
, loop
->step
);
405 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
406 fold_build1_loc (loc
, NEGATE_EXPR
,
408 fold_build1_loc (loc
, NEGATE_EXPR
,
412 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
413 fold_convert_loc (loc
, itype
,
415 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
416 if (count
!= NULL_TREE
)
417 count
= fold_build2_loc (loc
, MULT_EXPR
,
418 long_long_unsigned_type_node
,
422 if (TREE_CODE (count
) != INTEGER_CST
)
425 else if (count
&& !integer_zerop (count
))
432 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
433 || fd
->have_ordered
))
435 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
436 iter_type
= long_long_unsigned_type_node
;
438 iter_type
= long_integer_type_node
;
440 else if (collapse_iter
&& *collapse_iter
!= NULL
)
441 iter_type
= TREE_TYPE (*collapse_iter
);
442 fd
->iter_type
= iter_type
;
443 if (collapse_iter
&& *collapse_iter
== NULL
)
444 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
445 if (collapse_count
&& *collapse_count
== NULL
)
448 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
450 *collapse_count
= create_tmp_var (iter_type
, ".count");
453 if (fd
->collapse
> 1 || fd
->tiling
|| (fd
->ordered
&& loops
))
455 fd
->loop
.v
= *collapse_iter
;
456 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
457 fd
->loop
.n2
= *collapse_count
;
458 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
459 fd
->loop
.cond_code
= LT_EXPR
;
465 /* Build a call to GOMP_barrier. */
468 omp_build_barrier (tree lhs
)
470 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
471 : BUILT_IN_GOMP_BARRIER
);
472 gcall
*g
= gimple_build_call (fndecl
, 0);
474 gimple_call_set_lhs (g
, lhs
);
478 /* Return maximum possible vectorization factor for the target. */
485 || !flag_tree_loop_optimize
486 || (!flag_tree_loop_vectorize
487 && global_options_set
.x_flag_tree_loop_vectorize
))
490 auto_vector_sizes sizes
;
491 targetm
.vectorize
.autovectorize_vector_sizes (&sizes
, true);
492 if (!sizes
.is_empty ())
495 for (unsigned int i
= 0; i
< sizes
.length (); ++i
)
496 vf
= ordered_max (vf
, sizes
[i
]);
500 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
501 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
502 return GET_MODE_NUNITS (vqimode
);
507 /* Return maximum SIMT width if offloading may target SIMT hardware. */
510 omp_max_simt_vf (void)
514 if (ENABLE_OFFLOADING
)
515 for (const char *c
= getenv ("OFFLOAD_TARGET_NAMES"); c
;)
517 if (!strncmp (c
, "nvptx", strlen ("nvptx")))
519 else if ((c
= strchr (c
, ',')))
525 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
526 macro on gomp-constants.h. We do not check for overflow. */
529 oacc_launch_pack (unsigned code
, tree device
, unsigned op
)
533 res
= build_int_cst (unsigned_type_node
, GOMP_LAUNCH_PACK (code
, 0, op
));
536 device
= fold_build2 (LSHIFT_EXPR
, unsigned_type_node
,
537 device
, build_int_cst (unsigned_type_node
,
538 GOMP_LAUNCH_DEVICE_SHIFT
));
539 res
= fold_build2 (BIT_IOR_EXPR
, unsigned_type_node
, res
, device
);
544 /* FIXME: What is the following comment for? */
545 /* Look for compute grid dimension clauses and convert to an attribute
546 attached to FN. This permits the target-side code to (a) massage
547 the dimensions, (b) emit that data and (c) optimize. Non-constant
548 dimensions are pushed onto ARGS.
550 The attribute value is a TREE_LIST. A set of dimensions is
551 represented as a list of INTEGER_CST. Those that are runtime
552 exprs are represented as an INTEGER_CST of zero.
554 TODO: Normally the attribute will just contain a single such list. If
555 however it contains a list of lists, this will represent the use of
556 device_type. Each member of the outer list is an assoc list of
557 dimensions, keyed by the device type. The first entry will be the
558 default. Well, that's the plan. */
560 /* Replace any existing oacc fn attribute with updated dimensions. */
562 /* Variant working on a list of attributes. */
565 oacc_replace_fn_attrib_attr (tree attribs
, tree dims
)
567 tree ident
= get_identifier (OACC_FN_ATTRIB
);
569 /* If we happen to be present as the first attrib, drop it. */
570 if (attribs
&& TREE_PURPOSE (attribs
) == ident
)
571 attribs
= TREE_CHAIN (attribs
);
572 return tree_cons (ident
, dims
, attribs
);
575 /* Variant working on a function decl. */
578 oacc_replace_fn_attrib (tree fn
, tree dims
)
581 = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn
), dims
);
584 /* Scan CLAUSES for launch dimensions and attach them to the oacc
585 function attribute. Push any that are non-constant onto the ARGS
586 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
589 oacc_set_fn_attrib (tree fn
, tree clauses
, vec
<tree
> *args
)
591 /* Must match GOMP_DIM ordering. */
592 static const omp_clause_code ids
[]
593 = { OMP_CLAUSE_NUM_GANGS
, OMP_CLAUSE_NUM_WORKERS
,
594 OMP_CLAUSE_VECTOR_LENGTH
};
596 tree dims
[GOMP_DIM_MAX
];
598 tree attr
= NULL_TREE
;
599 unsigned non_const
= 0;
601 for (ix
= GOMP_DIM_MAX
; ix
--;)
603 tree clause
= omp_find_clause (clauses
, ids
[ix
]);
604 tree dim
= NULL_TREE
;
607 dim
= OMP_CLAUSE_EXPR (clause
, ids
[ix
]);
609 if (dim
&& TREE_CODE (dim
) != INTEGER_CST
)
611 dim
= integer_zero_node
;
612 non_const
|= GOMP_DIM_MASK (ix
);
614 attr
= tree_cons (NULL_TREE
, dim
, attr
);
617 oacc_replace_fn_attrib (fn
, attr
);
621 /* Push a dynamic argument set. */
622 args
->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM
,
623 NULL_TREE
, non_const
));
624 for (unsigned ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
625 if (non_const
& GOMP_DIM_MASK (ix
))
626 args
->safe_push (dims
[ix
]);
630 /* Verify OpenACC routine clauses.
632 Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
633 if it has already been marked in compatible way, and -1 if incompatible.
634 Upon returning, the chain of clauses will contain exactly one clause
635 specifying the level of parallelism. */
638 oacc_verify_routine_clauses (tree fndecl
, tree
*clauses
, location_t loc
,
639 const char *routine_str
)
641 tree c_level
= NULL_TREE
;
642 tree c_p
= NULL_TREE
;
643 for (tree c
= *clauses
; c
; c_p
= c
, c
= OMP_CLAUSE_CHAIN (c
))
644 switch (OMP_CLAUSE_CODE (c
))
646 case OMP_CLAUSE_GANG
:
647 case OMP_CLAUSE_WORKER
:
648 case OMP_CLAUSE_VECTOR
:
650 if (c_level
== NULL_TREE
)
652 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_CODE (c_level
))
654 /* This has already been diagnosed in the front ends. */
655 /* Drop the duplicate clause. */
656 gcc_checking_assert (c_p
!= NULL_TREE
);
657 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
662 error_at (OMP_CLAUSE_LOCATION (c
),
663 "%qs specifies a conflicting level of parallelism",
664 omp_clause_code_name
[OMP_CLAUSE_CODE (c
)]);
665 inform (OMP_CLAUSE_LOCATION (c_level
),
666 "... to the previous %qs clause here",
667 omp_clause_code_name
[OMP_CLAUSE_CODE (c_level
)]);
668 /* Drop the conflicting clause. */
669 gcc_checking_assert (c_p
!= NULL_TREE
);
670 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
677 if (c_level
== NULL_TREE
)
679 /* Default to an implicit 'seq' clause. */
680 c_level
= build_omp_clause (loc
, OMP_CLAUSE_SEQ
);
681 OMP_CLAUSE_CHAIN (c_level
) = *clauses
;
684 /* In *clauses, we now have exactly one clause specifying the level of
688 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl
));
689 if (attr
!= NULL_TREE
)
691 /* If a "#pragma acc routine" has already been applied, just verify
692 this one for compatibility. */
693 /* Collect previous directive's clauses. */
694 tree c_level_p
= NULL_TREE
;
695 for (tree c
= TREE_VALUE (attr
); c
; c
= OMP_CLAUSE_CHAIN (c
))
696 switch (OMP_CLAUSE_CODE (c
))
698 case OMP_CLAUSE_GANG
:
699 case OMP_CLAUSE_WORKER
:
700 case OMP_CLAUSE_VECTOR
:
702 gcc_checking_assert (c_level_p
== NULL_TREE
);
708 gcc_checking_assert (c_level_p
!= NULL_TREE
);
709 /* ..., and compare to current directive's, which we've already collected
713 /* Matching level of parallelism? */
714 if (OMP_CLAUSE_CODE (c_level
) != OMP_CLAUSE_CODE (c_level_p
))
717 c_diag_p
= c_level_p
;
724 if (c_diag
!= NULL_TREE
)
725 error_at (OMP_CLAUSE_LOCATION (c_diag
),
726 "incompatible %qs clause when applying"
727 " %<%s%> to %qD, which has already been"
728 " marked with an OpenACC 'routine' directive",
729 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)],
730 routine_str
, fndecl
);
731 else if (c_diag_p
!= NULL_TREE
)
733 "missing %qs clause when applying"
734 " %<%s%> to %qD, which has already been"
735 " marked with an OpenACC 'routine' directive",
736 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)],
737 routine_str
, fndecl
);
740 if (c_diag_p
!= NULL_TREE
)
741 inform (OMP_CLAUSE_LOCATION (c_diag_p
),
742 "... with %qs clause here",
743 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)]);
746 /* In the front ends, we don't preserve location information for the
747 OpenACC routine directive itself. However, that of c_level_p
749 location_t loc_routine
= OMP_CLAUSE_LOCATION (c_level_p
);
750 inform (loc_routine
, "... without %qs clause near to here",
751 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)]);
760 /* Process the OpenACC 'routine' directive clauses to generate an attribute
761 for the level of parallelism. All dimensions have a size of zero
762 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
763 can have a loop partitioned on it. non-zero indicates
764 yes, zero indicates no. By construction once a non-zero has been
765 reached, further inner dimensions must also be non-zero. We set
766 TREE_VALUE to zero for the dimensions that may be partitioned and
767 1 for the other ones -- if a loop is (erroneously) spawned at
768 an outer level, we don't want to try and partition it. */
771 oacc_build_routine_dims (tree clauses
)
773 /* Must match GOMP_DIM ordering. */
774 static const omp_clause_code ids
[]
775 = {OMP_CLAUSE_GANG
, OMP_CLAUSE_WORKER
, OMP_CLAUSE_VECTOR
, OMP_CLAUSE_SEQ
};
779 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
780 for (ix
= GOMP_DIM_MAX
+ 1; ix
--;)
781 if (OMP_CLAUSE_CODE (clauses
) == ids
[ix
])
786 gcc_checking_assert (level
>= 0);
788 tree dims
= NULL_TREE
;
790 for (ix
= GOMP_DIM_MAX
; ix
--;)
791 dims
= tree_cons (build_int_cst (boolean_type_node
, ix
>= level
),
792 build_int_cst (integer_type_node
, ix
< level
), dims
);
797 /* Retrieve the oacc function attrib and return it. Non-oacc
798 functions will return NULL. */
801 oacc_get_fn_attrib (tree fn
)
803 return lookup_attribute (OACC_FN_ATTRIB
, DECL_ATTRIBUTES (fn
));
806 /* Return true if FN is an OpenMP or OpenACC offloading function. */
809 offloading_function_p (tree fn
)
811 tree attrs
= DECL_ATTRIBUTES (fn
);
812 return (lookup_attribute ("omp declare target", attrs
)
813 || lookup_attribute ("omp target entrypoint", attrs
));
816 /* Extract an oacc execution dimension from FN. FN must be an
817 offloaded function or routine that has already had its execution
818 dimensions lowered to the target-specific values. */
821 oacc_get_fn_dim_size (tree fn
, int axis
)
823 tree attrs
= oacc_get_fn_attrib (fn
);
825 gcc_assert (axis
< GOMP_DIM_MAX
);
827 tree dims
= TREE_VALUE (attrs
);
829 dims
= TREE_CHAIN (dims
);
831 int size
= TREE_INT_CST_LOW (TREE_VALUE (dims
));
836 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
837 IFN_GOACC_DIM_SIZE call. */
840 oacc_get_ifn_dim_arg (const gimple
*stmt
)
842 gcc_checking_assert (gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_SIZE
843 || gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_POS
);
844 tree arg
= gimple_call_arg (stmt
, 0);
845 HOST_WIDE_INT axis
= TREE_INT_CST_LOW (arg
);
847 gcc_checking_assert (axis
>= 0 && axis
< GOMP_DIM_MAX
);