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 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
52 allocatable or pointer attribute. */
54 omp_is_allocatable_or_ptr (tree decl
)
56 return lang_hooks
.decls
.omp_is_allocatable_or_ptr (decl
);
59 /* Return true if DECL is a Fortran optional argument. */
62 omp_is_optional_argument (tree decl
)
64 return lang_hooks
.decls
.omp_is_optional_argument (decl
);
67 /* Return true if DECL is a reference type. */
70 omp_is_reference (tree decl
)
72 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
75 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or GT_EXPR,
76 given that V is the loop index variable and STEP is loop step. */
79 omp_adjust_for_condition (location_t loc
, enum tree_code
*cond_code
, tree
*n2
,
89 gcc_assert (TREE_CODE (step
) == INTEGER_CST
);
90 if (TREE_CODE (TREE_TYPE (v
)) == INTEGER_TYPE
)
92 if (integer_onep (step
))
96 gcc_assert (integer_minus_onep (step
));
102 tree unit
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v
)));
103 gcc_assert (TREE_CODE (unit
) == INTEGER_CST
);
104 if (tree_int_cst_equal (unit
, step
))
105 *cond_code
= LT_EXPR
;
108 gcc_assert (wi::neg (wi::to_widest (unit
))
109 == wi::to_widest (step
));
110 *cond_code
= GT_EXPR
;
117 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
118 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, 1);
120 *n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (*n2
), *n2
,
121 build_int_cst (TREE_TYPE (*n2
), 1));
122 *cond_code
= LT_EXPR
;
125 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
126 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, -1);
128 *n2
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (*n2
), *n2
,
129 build_int_cst (TREE_TYPE (*n2
), 1));
130 *cond_code
= GT_EXPR
;
137 /* Return the looping step from INCR, extracted from the step of a gimple omp
141 omp_get_for_step_from_incr (location_t loc
, tree incr
)
144 switch (TREE_CODE (incr
))
147 step
= TREE_OPERAND (incr
, 1);
149 case POINTER_PLUS_EXPR
:
150 step
= fold_convert (ssizetype
, TREE_OPERAND (incr
, 1));
153 step
= TREE_OPERAND (incr
, 1);
154 step
= fold_build1_loc (loc
, NEGATE_EXPR
, TREE_TYPE (step
), step
);
162 /* Extract the header elements of parallel loop FOR_STMT and store
166 omp_extract_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
167 struct omp_for_data_loop
*loops
)
169 tree t
, var
, *collapse_iter
, *collapse_count
;
170 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
171 struct omp_for_data_loop
*loop
;
173 struct omp_for_data_loop dummy_loop
;
174 location_t loc
= gimple_location (for_stmt
);
175 bool simd
= gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_SIMD
;
176 bool distribute
= gimple_omp_for_kind (for_stmt
)
177 == GF_OMP_FOR_KIND_DISTRIBUTE
;
178 bool taskloop
= gimple_omp_for_kind (for_stmt
)
179 == GF_OMP_FOR_KIND_TASKLOOP
;
182 fd
->for_stmt
= for_stmt
;
184 fd
->have_nowait
= distribute
|| simd
;
185 fd
->have_ordered
= false;
186 fd
->have_reductemp
= false;
187 fd
->have_pointer_condtemp
= false;
188 fd
->have_scantemp
= false;
189 fd
->have_nonctrl_scantemp
= false;
190 fd
->lastprivate_conditional
= 0;
191 fd
->tiling
= NULL_TREE
;
194 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
195 fd
->sched_modifiers
= 0;
196 fd
->chunk_size
= NULL_TREE
;
197 fd
->simd_schedule
= false;
198 collapse_iter
= NULL
;
199 collapse_count
= NULL
;
201 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
202 switch (OMP_CLAUSE_CODE (t
))
204 case OMP_CLAUSE_NOWAIT
:
205 fd
->have_nowait
= true;
207 case OMP_CLAUSE_ORDERED
:
208 fd
->have_ordered
= true;
209 if (OMP_CLAUSE_ORDERED_EXPR (t
))
210 fd
->ordered
= tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t
));
212 case OMP_CLAUSE_SCHEDULE
:
213 gcc_assert (!distribute
&& !taskloop
);
215 = (enum omp_clause_schedule_kind
)
216 (OMP_CLAUSE_SCHEDULE_KIND (t
) & OMP_CLAUSE_SCHEDULE_MASK
);
217 fd
->sched_modifiers
= (OMP_CLAUSE_SCHEDULE_KIND (t
)
218 & ~OMP_CLAUSE_SCHEDULE_MASK
);
219 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
220 fd
->simd_schedule
= OMP_CLAUSE_SCHEDULE_SIMD (t
);
222 case OMP_CLAUSE_DIST_SCHEDULE
:
223 gcc_assert (distribute
);
224 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
226 case OMP_CLAUSE_COLLAPSE
:
227 fd
->collapse
= tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t
));
228 if (fd
->collapse
> 1)
230 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
231 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
234 case OMP_CLAUSE_TILE
:
235 fd
->tiling
= OMP_CLAUSE_TILE_LIST (t
);
236 fd
->collapse
= list_length (fd
->tiling
);
237 gcc_assert (fd
->collapse
);
238 collapse_iter
= &OMP_CLAUSE_TILE_ITERVAR (t
);
239 collapse_count
= &OMP_CLAUSE_TILE_COUNT (t
);
241 case OMP_CLAUSE__REDUCTEMP_
:
242 fd
->have_reductemp
= true;
244 case OMP_CLAUSE_LASTPRIVATE
:
245 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t
))
246 fd
->lastprivate_conditional
++;
248 case OMP_CLAUSE__CONDTEMP_
:
249 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t
))))
250 fd
->have_pointer_condtemp
= true;
252 case OMP_CLAUSE__SCANTEMP_
:
253 fd
->have_scantemp
= true;
254 if (!OMP_CLAUSE__SCANTEMP__ALLOC (t
)
255 && !OMP_CLAUSE__SCANTEMP__CONTROL (t
))
256 fd
->have_nonctrl_scantemp
= true;
262 if (fd
->collapse
> 1 || fd
->tiling
)
265 fd
->loops
= &fd
->loop
;
267 if (fd
->ordered
&& fd
->collapse
== 1 && loops
!= NULL
)
272 collapse_iter
= &iterv
;
273 collapse_count
= &countv
;
276 /* FIXME: for now map schedule(auto) to schedule(static).
277 There should be analysis to determine whether all iterations
278 are approximately the same amount of work (then schedule(static)
279 is best) or if it varies (then schedule(dynamic,N) is better). */
280 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
282 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
283 gcc_assert (fd
->chunk_size
== NULL
);
285 gcc_assert ((fd
->collapse
== 1 && !fd
->tiling
) || collapse_iter
!= NULL
);
287 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_RUNTIME
;
288 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
289 gcc_assert (fd
->chunk_size
== NULL
);
290 else if (fd
->chunk_size
== NULL
)
292 /* We only need to compute a default chunk size for ordered
293 static loops and dynamic loops. */
294 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
296 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
297 ? integer_zero_node
: integer_one_node
;
300 int cnt
= fd
->ordered
? fd
->ordered
: fd
->collapse
;
301 for (i
= 0; i
< cnt
; i
++)
306 && (fd
->ordered
== 0 || loops
== NULL
))
308 else if (loops
!= NULL
)
313 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
314 gcc_assert (SSA_VAR_P (loop
->v
));
315 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
316 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
317 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
318 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
320 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
321 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
322 gcc_assert (loop
->cond_code
!= NE_EXPR
323 || (gimple_omp_for_kind (for_stmt
)
324 != GF_OMP_FOR_KIND_OACC_LOOP
));
326 t
= gimple_omp_for_incr (for_stmt
, i
);
327 gcc_assert (TREE_OPERAND (t
, 0) == var
);
328 loop
->step
= omp_get_for_step_from_incr (loc
, t
);
330 omp_adjust_for_condition (loc
, &loop
->cond_code
, &loop
->n2
, loop
->v
,
334 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
335 && !fd
->have_ordered
))
337 if (fd
->collapse
== 1 && !fd
->tiling
)
338 iter_type
= TREE_TYPE (loop
->v
);
340 || TYPE_PRECISION (iter_type
)
341 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
343 = build_nonstandard_integer_type
344 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
346 else if (iter_type
!= long_long_unsigned_type_node
)
348 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
349 iter_type
= long_long_unsigned_type_node
;
350 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
351 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
352 >= TYPE_PRECISION (iter_type
))
356 if (loop
->cond_code
== LT_EXPR
)
357 n
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
358 loop
->n2
, loop
->step
);
361 if (TREE_CODE (n
) != INTEGER_CST
362 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
363 iter_type
= long_long_unsigned_type_node
;
365 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
366 > TYPE_PRECISION (iter_type
))
370 if (loop
->cond_code
== LT_EXPR
)
373 n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
374 loop
->n2
, loop
->step
);
378 n1
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (loop
->v
),
379 loop
->n2
, loop
->step
);
382 if (TREE_CODE (n1
) != INTEGER_CST
383 || TREE_CODE (n2
) != INTEGER_CST
384 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
385 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
386 iter_type
= long_long_unsigned_type_node
;
390 if (i
>= fd
->collapse
)
393 if (collapse_count
&& *collapse_count
== NULL
)
395 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
396 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
397 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
398 if (t
&& integer_zerop (t
))
399 count
= build_zero_cst (long_long_unsigned_type_node
);
400 else if ((i
== 0 || count
!= NULL_TREE
)
401 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
402 && TREE_CONSTANT (loop
->n1
)
403 && TREE_CONSTANT (loop
->n2
)
404 && TREE_CODE (loop
->step
) == INTEGER_CST
)
406 tree itype
= TREE_TYPE (loop
->v
);
408 if (POINTER_TYPE_P (itype
))
409 itype
= signed_type_for (itype
);
410 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
411 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
,
412 fold_convert_loc (loc
, itype
, loop
->step
),
414 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
415 fold_convert_loc (loc
, itype
, loop
->n2
));
416 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
417 fold_convert_loc (loc
, itype
, loop
->n1
));
418 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
420 tree step
= fold_convert_loc (loc
, itype
, loop
->step
);
421 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
422 fold_build1_loc (loc
, NEGATE_EXPR
,
424 fold_build1_loc (loc
, NEGATE_EXPR
,
428 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
429 fold_convert_loc (loc
, itype
,
431 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
432 if (count
!= NULL_TREE
)
433 count
= fold_build2_loc (loc
, MULT_EXPR
,
434 long_long_unsigned_type_node
,
438 if (TREE_CODE (count
) != INTEGER_CST
)
441 else if (count
&& !integer_zerop (count
))
448 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
449 || fd
->have_ordered
))
451 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
452 iter_type
= long_long_unsigned_type_node
;
454 iter_type
= long_integer_type_node
;
456 else if (collapse_iter
&& *collapse_iter
!= NULL
)
457 iter_type
= TREE_TYPE (*collapse_iter
);
458 fd
->iter_type
= iter_type
;
459 if (collapse_iter
&& *collapse_iter
== NULL
)
460 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
461 if (collapse_count
&& *collapse_count
== NULL
)
464 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
466 *collapse_count
= create_tmp_var (iter_type
, ".count");
469 if (fd
->collapse
> 1 || fd
->tiling
|| (fd
->ordered
&& loops
))
471 fd
->loop
.v
= *collapse_iter
;
472 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
473 fd
->loop
.n2
= *collapse_count
;
474 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
475 fd
->loop
.cond_code
= LT_EXPR
;
481 /* Build a call to GOMP_barrier. */
484 omp_build_barrier (tree lhs
)
486 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
487 : BUILT_IN_GOMP_BARRIER
);
488 gcall
*g
= gimple_build_call (fndecl
, 0);
490 gimple_call_set_lhs (g
, lhs
);
494 /* Return maximum possible vectorization factor for the target. */
501 || !flag_tree_loop_optimize
502 || (!flag_tree_loop_vectorize
503 && global_options_set
.x_flag_tree_loop_vectorize
))
506 auto_vector_sizes sizes
;
507 targetm
.vectorize
.autovectorize_vector_sizes (&sizes
, true);
508 if (!sizes
.is_empty ())
511 for (unsigned int i
= 0; i
< sizes
.length (); ++i
)
512 vf
= ordered_max (vf
, sizes
[i
]);
516 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
517 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
518 return GET_MODE_NUNITS (vqimode
);
523 /* Return maximum SIMT width if offloading may target SIMT hardware. */
526 omp_max_simt_vf (void)
530 if (ENABLE_OFFLOADING
)
531 for (const char *c
= getenv ("OFFLOAD_TARGET_NAMES"); c
;)
533 if (!strncmp (c
, "nvptx", strlen ("nvptx")))
535 else if ((c
= strchr (c
, ',')))
541 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
542 macro on gomp-constants.h. We do not check for overflow. */
545 oacc_launch_pack (unsigned code
, tree device
, unsigned op
)
549 res
= build_int_cst (unsigned_type_node
, GOMP_LAUNCH_PACK (code
, 0, op
));
552 device
= fold_build2 (LSHIFT_EXPR
, unsigned_type_node
,
553 device
, build_int_cst (unsigned_type_node
,
554 GOMP_LAUNCH_DEVICE_SHIFT
));
555 res
= fold_build2 (BIT_IOR_EXPR
, unsigned_type_node
, res
, device
);
560 /* FIXME: What is the following comment for? */
561 /* Look for compute grid dimension clauses and convert to an attribute
562 attached to FN. This permits the target-side code to (a) massage
563 the dimensions, (b) emit that data and (c) optimize. Non-constant
564 dimensions are pushed onto ARGS.
566 The attribute value is a TREE_LIST. A set of dimensions is
567 represented as a list of INTEGER_CST. Those that are runtime
568 exprs are represented as an INTEGER_CST of zero.
570 TODO: Normally the attribute will just contain a single such list. If
571 however it contains a list of lists, this will represent the use of
572 device_type. Each member of the outer list is an assoc list of
573 dimensions, keyed by the device type. The first entry will be the
574 default. Well, that's the plan. */
576 /* Replace any existing oacc fn attribute with updated dimensions. */
578 /* Variant working on a list of attributes. */
581 oacc_replace_fn_attrib_attr (tree attribs
, tree dims
)
583 tree ident
= get_identifier (OACC_FN_ATTRIB
);
585 /* If we happen to be present as the first attrib, drop it. */
586 if (attribs
&& TREE_PURPOSE (attribs
) == ident
)
587 attribs
= TREE_CHAIN (attribs
);
588 return tree_cons (ident
, dims
, attribs
);
591 /* Variant working on a function decl. */
594 oacc_replace_fn_attrib (tree fn
, tree dims
)
597 = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn
), dims
);
600 /* Scan CLAUSES for launch dimensions and attach them to the oacc
601 function attribute. Push any that are non-constant onto the ARGS
602 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
605 oacc_set_fn_attrib (tree fn
, tree clauses
, vec
<tree
> *args
)
607 /* Must match GOMP_DIM ordering. */
608 static const omp_clause_code ids
[]
609 = { OMP_CLAUSE_NUM_GANGS
, OMP_CLAUSE_NUM_WORKERS
,
610 OMP_CLAUSE_VECTOR_LENGTH
};
612 tree dims
[GOMP_DIM_MAX
];
614 tree attr
= NULL_TREE
;
615 unsigned non_const
= 0;
617 for (ix
= GOMP_DIM_MAX
; ix
--;)
619 tree clause
= omp_find_clause (clauses
, ids
[ix
]);
620 tree dim
= NULL_TREE
;
623 dim
= OMP_CLAUSE_EXPR (clause
, ids
[ix
]);
625 if (dim
&& TREE_CODE (dim
) != INTEGER_CST
)
627 dim
= integer_zero_node
;
628 non_const
|= GOMP_DIM_MASK (ix
);
630 attr
= tree_cons (NULL_TREE
, dim
, attr
);
633 oacc_replace_fn_attrib (fn
, attr
);
637 /* Push a dynamic argument set. */
638 args
->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM
,
639 NULL_TREE
, non_const
));
640 for (unsigned ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
641 if (non_const
& GOMP_DIM_MASK (ix
))
642 args
->safe_push (dims
[ix
]);
646 /* Verify OpenACC routine clauses.
648 Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
649 if it has already been marked in compatible way, and -1 if incompatible.
650 Upon returning, the chain of clauses will contain exactly one clause
651 specifying the level of parallelism. */
654 oacc_verify_routine_clauses (tree fndecl
, tree
*clauses
, location_t loc
,
655 const char *routine_str
)
657 tree c_level
= NULL_TREE
;
658 tree c_p
= NULL_TREE
;
659 for (tree c
= *clauses
; c
; c_p
= c
, c
= OMP_CLAUSE_CHAIN (c
))
660 switch (OMP_CLAUSE_CODE (c
))
662 case OMP_CLAUSE_GANG
:
663 case OMP_CLAUSE_WORKER
:
664 case OMP_CLAUSE_VECTOR
:
666 if (c_level
== NULL_TREE
)
668 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_CODE (c_level
))
670 /* This has already been diagnosed in the front ends. */
671 /* Drop the duplicate clause. */
672 gcc_checking_assert (c_p
!= NULL_TREE
);
673 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
678 error_at (OMP_CLAUSE_LOCATION (c
),
679 "%qs specifies a conflicting level of parallelism",
680 omp_clause_code_name
[OMP_CLAUSE_CODE (c
)]);
681 inform (OMP_CLAUSE_LOCATION (c_level
),
682 "... to the previous %qs clause here",
683 omp_clause_code_name
[OMP_CLAUSE_CODE (c_level
)]);
684 /* Drop the conflicting clause. */
685 gcc_checking_assert (c_p
!= NULL_TREE
);
686 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
693 if (c_level
== NULL_TREE
)
695 /* Default to an implicit 'seq' clause. */
696 c_level
= build_omp_clause (loc
, OMP_CLAUSE_SEQ
);
697 OMP_CLAUSE_CHAIN (c_level
) = *clauses
;
700 /* In *clauses, we now have exactly one clause specifying the level of
704 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl
));
705 if (attr
!= NULL_TREE
)
707 /* If a "#pragma acc routine" has already been applied, just verify
708 this one for compatibility. */
709 /* Collect previous directive's clauses. */
710 tree c_level_p
= NULL_TREE
;
711 for (tree c
= TREE_VALUE (attr
); c
; c
= OMP_CLAUSE_CHAIN (c
))
712 switch (OMP_CLAUSE_CODE (c
))
714 case OMP_CLAUSE_GANG
:
715 case OMP_CLAUSE_WORKER
:
716 case OMP_CLAUSE_VECTOR
:
718 gcc_checking_assert (c_level_p
== NULL_TREE
);
724 gcc_checking_assert (c_level_p
!= NULL_TREE
);
725 /* ..., and compare to current directive's, which we've already collected
729 /* Matching level of parallelism? */
730 if (OMP_CLAUSE_CODE (c_level
) != OMP_CLAUSE_CODE (c_level_p
))
733 c_diag_p
= c_level_p
;
740 if (c_diag
!= NULL_TREE
)
741 error_at (OMP_CLAUSE_LOCATION (c_diag
),
742 "incompatible %qs clause when applying"
743 " %<%s%> to %qD, which has already been"
744 " marked with an OpenACC 'routine' directive",
745 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)],
746 routine_str
, fndecl
);
747 else if (c_diag_p
!= NULL_TREE
)
749 "missing %qs clause when applying"
750 " %<%s%> to %qD, which has already been"
751 " marked with an OpenACC 'routine' directive",
752 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)],
753 routine_str
, fndecl
);
756 if (c_diag_p
!= NULL_TREE
)
757 inform (OMP_CLAUSE_LOCATION (c_diag_p
),
758 "... with %qs clause here",
759 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)]);
762 /* In the front ends, we don't preserve location information for the
763 OpenACC routine directive itself. However, that of c_level_p
765 location_t loc_routine
= OMP_CLAUSE_LOCATION (c_level_p
);
766 inform (loc_routine
, "... without %qs clause near to here",
767 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)]);
776 /* Process the OpenACC 'routine' directive clauses to generate an attribute
777 for the level of parallelism. All dimensions have a size of zero
778 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
779 can have a loop partitioned on it. non-zero indicates
780 yes, zero indicates no. By construction once a non-zero has been
781 reached, further inner dimensions must also be non-zero. We set
782 TREE_VALUE to zero for the dimensions that may be partitioned and
783 1 for the other ones -- if a loop is (erroneously) spawned at
784 an outer level, we don't want to try and partition it. */
787 oacc_build_routine_dims (tree clauses
)
789 /* Must match GOMP_DIM ordering. */
790 static const omp_clause_code ids
[]
791 = {OMP_CLAUSE_GANG
, OMP_CLAUSE_WORKER
, OMP_CLAUSE_VECTOR
, OMP_CLAUSE_SEQ
};
795 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
796 for (ix
= GOMP_DIM_MAX
+ 1; ix
--;)
797 if (OMP_CLAUSE_CODE (clauses
) == ids
[ix
])
802 gcc_checking_assert (level
>= 0);
804 tree dims
= NULL_TREE
;
806 for (ix
= GOMP_DIM_MAX
; ix
--;)
807 dims
= tree_cons (build_int_cst (boolean_type_node
, ix
>= level
),
808 build_int_cst (integer_type_node
, ix
< level
), dims
);
813 /* Retrieve the oacc function attrib and return it. Non-oacc
814 functions will return NULL. */
817 oacc_get_fn_attrib (tree fn
)
819 return lookup_attribute (OACC_FN_ATTRIB
, DECL_ATTRIBUTES (fn
));
822 /* Return true if FN is an OpenMP or OpenACC offloading function. */
825 offloading_function_p (tree fn
)
827 tree attrs
= DECL_ATTRIBUTES (fn
);
828 return (lookup_attribute ("omp declare target", attrs
)
829 || lookup_attribute ("omp target entrypoint", attrs
));
832 /* Extract an oacc execution dimension from FN. FN must be an
833 offloaded function or routine that has already had its execution
834 dimensions lowered to the target-specific values. */
837 oacc_get_fn_dim_size (tree fn
, int axis
)
839 tree attrs
= oacc_get_fn_attrib (fn
);
841 gcc_assert (axis
< GOMP_DIM_MAX
);
843 tree dims
= TREE_VALUE (attrs
);
845 dims
= TREE_CHAIN (dims
);
847 int size
= TREE_INT_CST_LOW (TREE_VALUE (dims
));
852 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
853 IFN_GOACC_DIM_SIZE call. */
856 oacc_get_ifn_dim_arg (const gimple
*stmt
)
858 gcc_checking_assert (gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_SIZE
859 || gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_POS
);
860 tree arg
= gimple_call_arg (stmt
, 0);
861 HOST_WIDE_INT axis
= TREE_INT_CST_LOW (arg
);
863 gcc_checking_assert (axis
>= 0 && axis
< GOMP_DIM_MAX
);