All the statements starting with OMP_
represent directives and
clauses used by the OpenMP API https://www.openmp.org.
OMP_PARALLEL
Represents #pragma omp parallel [clause1 … clauseN]
. It
has four operands:
Operand OMP_PARALLEL_BODY
is valid while in GENERIC and
High GIMPLE forms. It contains the body of code to be executed
by all the threads. During GIMPLE lowering, this operand becomes
NULL
and the body is emitted linearly after
OMP_PARALLEL
.
Operand OMP_PARALLEL_CLAUSES
is the list of clauses
associated with the directive.
Operand OMP_PARALLEL_FN
is created by
pass_lower_omp
, it contains the FUNCTION_DECL
for the function that will contain the body of the parallel
region.
Operand OMP_PARALLEL_DATA_ARG
is also created by
pass_lower_omp
. If there are shared variables to be
communicated to the children threads, this operand will contain
the VAR_DECL
that contains all the shared values and
variables.
OMP_FOR
OMP_SIMD
OMP_DISTRIBUTE
OMP_TASKLOOP
OMP_LOOP
Represents #pragma omp for [clause1 … clauseN]
and
related loop constructs (respectively).
A single OMP_FOR
node represents an entire nest of collapsed
loops; as noted below, some of its arguments are vectors of length
equal to the collapse depth, and the corresponding elements holding
data specific to a particular loop in the nest. These vectors are
numbered from the outside in so that the outermost loop is element 0.
These constructs have seven operands:
Operand OMP_FOR_BODY
contains the loop body.
Operand OMP_FOR_CLAUSES
is the list of clauses
associated with the directive.
Operand OMP_FOR_INIT
is a vector containing iteration
variable initializations of the form VAR = N1
.
Operand OMP_FOR_COND
is vector containing loop
conditional expressions of the form VAR {<,>,<=,>=,!=} N2
.
Operand OMP_FOR_INCR
is a vector containing loop index
increment expressions of the form VAR {+=,-=} INCR
.
Operand OMP_FOR_PRE_BODY
contains side effect code from
operands OMP_FOR_INIT
, OMP_FOR_COND
and
OMP_FOR_INCR
. These side effects are part of the
OMP_FOR
block but must be evaluated before the start of
loop body. OMP_FOR_PRE_BODY
specifically
includes DECL_EXPR
s for iteration variables that are
declared in the nested for
loops.
Note this field is not a vector; it may be null, but otherwise is
usually a statement list collecting the side effect code from all
the collapsed loops.
Operand OMP_FOR_ORIG_DECLS
holds VAR_DECLS
for the
original user-specified iterator variables in the source code.
In some cases, like C++ class iterators or range for
with
decomposition, the for
loop is rewritten by the front end to
use a temporary iteration variable. The purpose of this field is to
make the original variables available to the gimplifier so it can
adjust their data-sharing attributes and diagnose errors.
OMP_FOR_ORIG_DECLS
is a vector field, with each element holding
a list of VAR_DECLS
for the corresponding collapse level.
The loop index variable VAR
must be an integer variable,
which is implicitly private to each thread. For rectangular loops,
the bounds N1
and N2
and the increment expression
INCR
are required to be loop-invariant integer expressions
that are evaluated without any synchronization. The evaluation order,
frequency of evaluation and side effects are otherwise unspecified
by the standard.
For non-rectangular loops, in which the bounds of an inner loop depend
on the index of an outer loop, the bit OMP_FOR_NON_RECTANGULAR
must be set. In this case N1
and N2
are not ordinary
expressions, but instead a TREE_VEC
with three elements:
the DECL
for the outer loop variable, a multiplication
factor, and an offset.
OMP_SECTIONS
Represents #pragma omp sections [clause1 … clauseN]
.
Operand OMP_SECTIONS_BODY
contains the sections body,
which in turn contains a set of OMP_SECTION
nodes for
each of the concurrent sections delimited by #pragma omp
section
.
Operand OMP_SECTIONS_CLAUSES
is the list of clauses
associated with the directive.
OMP_SECTION
Section delimiter for OMP_SECTIONS
.
OMP_SINGLE
Represents #pragma omp single
.
Operand OMP_SINGLE_BODY
contains the body of code to be
executed by a single thread.
Operand OMP_SINGLE_CLAUSES
is the list of clauses
associated with the directive.
OMP_MASTER
Represents #pragma omp master
.
Operand OMP_MASTER_BODY
contains the body of code to be
executed by the master thread.
OMP_ORDERED
Represents #pragma omp ordered
.
Operand OMP_ORDERED_BODY
contains the body of code to be
executed in the sequential order dictated by the loop index
variable.
OMP_CRITICAL
Represents #pragma omp critical [name]
.
Operand OMP_CRITICAL_BODY
is the critical section.
Operand OMP_CRITICAL_NAME
is an optional identifier to
label the critical section.
OMP_RETURN
This does not represent any OpenMP directive, it is an artificial
marker to indicate the end of the body of an OpenMP. It is used
by the flow graph (tree-cfg.cc
) and OpenMP region
building code (omp-low.cc
).
OMP_CONTINUE
Similarly, this instruction does not represent an OpenMP
directive, it is used by OMP_FOR
(and similar codes) as well as
OMP_SECTIONS
to mark the place where the code needs to
loop to the next iteration, or the next section, respectively.
In some cases, OMP_CONTINUE
is placed right before
OMP_RETURN
. But if there are cleanups that need to
occur right after the looping body, it will be emitted between
OMP_CONTINUE
and OMP_RETURN
.
OMP_STRUCTURED_BLOCK
This is another statement that doesn’t correspond to an OpenMP directive.
It is used to mark sections of code in another directive that must
be structured block sequences, in particular for sequences of intervening code
in the body of an OMP_FOR
. It is not necessary to use this when the
entire body of a directive is required to be a structured block sequence,
since that is implicit in the representation of the corresponding node.
This tree node is used only to allow error checking transfers of control
in/out of the structured block sequence after gimplification.
It has a single operand (OMP_STRUCTURED_BLOCK_BODY
) that is
the code within the structured block sequence.
OMP_ATOMIC
Represents #pragma omp atomic
.
Operand 0 is the address at which the atomic operation is to be performed.
Operand 1 is the expression to evaluate. The gimplifier tries three alternative code generation strategies. Whenever possible, an atomic update built-in is used. If that fails, a compare-and-swap loop is attempted. If that also fails, a regular critical section around the expression is used.
OMP_CLAUSE
Represents clauses associated with one of the OMP_
directives.
Clauses are represented by separate subcodes defined in
tree.h. Clauses codes can be one of:
OMP_CLAUSE_PRIVATE
, OMP_CLAUSE_SHARED
,
OMP_CLAUSE_FIRSTPRIVATE
,
OMP_CLAUSE_LASTPRIVATE
, OMP_CLAUSE_COPYIN
,
OMP_CLAUSE_COPYPRIVATE
, OMP_CLAUSE_IF
,
OMP_CLAUSE_NUM_THREADS
, OMP_CLAUSE_SCHEDULE
,
OMP_CLAUSE_NOWAIT
, OMP_CLAUSE_ORDERED
,
OMP_CLAUSE_DEFAULT
, OMP_CLAUSE_REDUCTION
,
OMP_CLAUSE_COLLAPSE
, OMP_CLAUSE_UNTIED
,
OMP_CLAUSE_FINAL
, and OMP_CLAUSE_MERGEABLE
. Each code
represents the corresponding OpenMP clause.
Clauses associated with the same directive are chained together
via OMP_CLAUSE_CHAIN
. Those clauses that accept a list
of variables are restricted to exactly one, accessed with
OMP_CLAUSE_VAR
. Therefore, multiple variables under the
same clause C
need to be represented as multiple C
clauses
chained together. This facilitates adding new clauses during
compilation.
OMP_METADIRECTIVE
Represents #pragma omp metadirective
. This node has one field,
accessed by the OMP_METADIRECTIVE_VARIANTS (node)
macro.
Metadirective variants are represented internally as TREE_LIST
nodes
but you should use the interface provided in tree.h to
access their components.
OMP_METADIRECTIVE_VARIANT_SELECTOR (variant)
is the selector associated with the variant; this is null for the
‘otherwise’/‘default’ alternative.
OMP_METADIRECTIVE_VARIANT_DIRECTIVE (variant)
is the
nested directive for the variant.
OMP_METADIRECTIVE_VARIANT_BODY (variant)
represents
statements following a nested standalone or utility directive.
In other cases, this field is null and the body is part of the
nested directive instead.
Metadirective context selectors (as well as context selectors for
#pragma omp declare variant
) are also represented internally using
a TREE_LIST
representation but with accessors and constructors
declared in omp-general.h. A complete context selector is a list of
trait-set selectors, which are in turn composed of a list of trait selectors,
each of which may have a list of trait properties.
Identifiers for trait-set selectors and trait selectors are enums
defined in omp-selectors.h, while trait property identifiers are
string constants.
OMP_NEXT_VARIANT
Some OpenMP variant constructs cannot be resolved until the ompdevlow pass,
in omp-offload.cc. The gimplifier turns these into a switch
statement in a loop, using OMP_NEXT_VARIANT
as a placeholder to set
the switch control variable. The ompdevlow pass replaces these with constant
integers after resolution.
OMP_NEXT_VARIANT
has two operands. Operand 0 is
OMP_NEXT_VARIANT_INDEX
, an INTEGER_CST
for the current current
index. Operand 1 is OMP_NEXT_VARIANT_STATE
, a TREE_LIST
shared
among all OMP_NEXT_VARIANT
expressions for the same variant construct
that holds resolution state information for that construct.
OMP_TARGET_DEVICE_MATCHES
Similarly to OMP_NEXT_VARIANT
, this tree node is a placeholder that is
resolved in the ompdevlow pass. It is used to implement the
target_device
dynamic selector. The gimplifier generates these
nodes and arranges for them to be executed on the device_num
specified
in the selector. The ompdevlow pass replaces each
OMP_TARGET_DEVICE_MATCHES
node with a constant value, depending on the
corresponding kind, arch, or isa properties configured for the offload compiler.
OMP_TARGET_DEVICES
has two operands. Operand 0 is
OMP_TARGET_DEVICE_MATCHES_SELECTOR
, an INTEGER_CST
encoding one of the constants OMP_TRAIT_DEVICE_KIND
,
OMP_TRAIT_DEVICE_ARCH
, or OMP_TRAIT_DEVICE_ISA
. Operand
1 is OMP_TARGET_DEVICE_MATCHES_PROPERTIES
, a TREE_LIST
using the same internal representation as the properties part of the selector.