2020-09-11 01:34:37 +08:00
|
|
|
|
<!--===- docs/OpenMP-semantics.md
|
|
|
|
|
|
|
|
|
|
Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
|
See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
|
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
|
|
2019-08-28 05:38:48 +08:00
|
|
|
|
# OpenMP Semantic Analysis
|
|
|
|
|
|
2020-09-11 21:17:19 +08:00
|
|
|
|
```eval_rst
|
|
|
|
|
.. contents::
|
|
|
|
|
:local:
|
|
|
|
|
```
|
|
|
|
|
|
2019-08-28 09:12:50 +08:00
|
|
|
|
## OpenMP for F18
|
2019-08-28 05:38:48 +08:00
|
|
|
|
|
|
|
|
|
1. Define and document the parse tree representation for
|
|
|
|
|
* Directives (listed below)
|
|
|
|
|
* Clauses (listed below)
|
|
|
|
|
* Documentation
|
|
|
|
|
1. All the directives and clauses need source provenance for messages
|
|
|
|
|
1. Define and document how an OpenMP directive in the parse tree
|
|
|
|
|
will be represented as the parent of the statement(s)
|
|
|
|
|
to which the directive applies.
|
|
|
|
|
The parser itself will not be able to construct this representation;
|
|
|
|
|
there will be subsequent passes that do so
|
|
|
|
|
just like for example _do-stmt_ and _do-construct_.
|
|
|
|
|
1. Define and document the symbol table extensions
|
|
|
|
|
1. Define and document the module file extensions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Directives
|
|
|
|
|
|
|
|
|
|
OpenMP divides directives into three categories as follows.
|
|
|
|
|
The directives that are in the same categories share some characteristics.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### Declarative directives
|
|
|
|
|
|
2019-08-28 09:12:50 +08:00
|
|
|
|
An OpenMP directive may only be placed in a declarative context.
|
2019-08-28 05:38:48 +08:00
|
|
|
|
A declarative directive results in one or more declarations only;
|
|
|
|
|
it is not associated with the immediate execution of any user code.
|
|
|
|
|
|
|
|
|
|
List of existing ones:
|
|
|
|
|
* declare simd
|
|
|
|
|
* declare target
|
|
|
|
|
* threadprivate
|
|
|
|
|
* declare reduction
|
|
|
|
|
|
|
|
|
|
There is a parser node for each of these directives and
|
|
|
|
|
the parser node saves information associated with the directive,
|
|
|
|
|
for example,
|
|
|
|
|
the name of the procedure-name in the `declare simd` directive.
|
|
|
|
|
|
|
|
|
|
Each parse tree node keeps source provenance,
|
|
|
|
|
one for the directive name itself and
|
|
|
|
|
one for the entire directive starting from the directive name.
|
|
|
|
|
|
|
|
|
|
A top-level class, `OpenMPDeclarativeConstruct`,
|
|
|
|
|
holds all four of the node types as discriminated unions
|
|
|
|
|
along with the source provenance for the entire directive
|
|
|
|
|
starting from `!$OMP`.
|
|
|
|
|
|
2019-08-28 09:12:50 +08:00
|
|
|
|
In `parser-tree.h`,
|
2019-08-28 05:38:48 +08:00
|
|
|
|
`OpenMPDeclarativeConstruct` is part
|
|
|
|
|
of the `SpecificationConstruct` and `SpecificationPart`
|
|
|
|
|
in F18 because
|
|
|
|
|
a declarative directive can only be placed in the specification part
|
|
|
|
|
of a Fortran program.
|
|
|
|
|
|
2019-08-28 09:12:50 +08:00
|
|
|
|
All the `Names` or `Designators` associated
|
2019-08-28 05:38:48 +08:00
|
|
|
|
with the declarative directive will be resolved in later phases.
|
|
|
|
|
|
|
|
|
|
#### Executable directives
|
|
|
|
|
|
|
|
|
|
An OpenMP directive that is **not** declarative.
|
|
|
|
|
That is, it may only be placed in an executable context.
|
|
|
|
|
It contains stand-alone directives and constructs
|
|
|
|
|
that are associated with code blocks.
|
|
|
|
|
The stand-alone directive is described in the next section.
|
|
|
|
|
|
|
|
|
|
The constructs associated with code blocks listed below
|
|
|
|
|
share a similar structure:
|
|
|
|
|
_Begin Directive_, _Clause List_, _Code Block_, _End Directive_.
|
|
|
|
|
The _End Directive_ is optional for constructs
|
|
|
|
|
like Loop-associated constructs.
|
|
|
|
|
|
|
|
|
|
* Block-associated constructs (`OpenMPBlockConstruct`)
|
|
|
|
|
* Loop-associated constructs (`OpenMPLoopConstruct`)
|
|
|
|
|
* Atomic construct (`OpenMPAtomicConstruct`)
|
|
|
|
|
* Sections Construct (`OpenMPSectionsConstruct`,
|
|
|
|
|
contains Sections/Parallel Sections constructs)
|
|
|
|
|
* Critical Construct (`OpenMPCriticalConstruct`)
|
|
|
|
|
|
|
|
|
|
A top-level class, `OpenMPConstruct`,
|
|
|
|
|
includes stand-alone directive and constructs
|
|
|
|
|
listed above as discriminated unions.
|
|
|
|
|
|
|
|
|
|
In the `parse-tree.h`, `OpenMPConstruct` is an element
|
|
|
|
|
of the `ExecutableConstruct`.
|
|
|
|
|
|
2019-08-28 09:12:50 +08:00
|
|
|
|
All the `Names` or `Designators` associated
|
2019-08-28 05:38:48 +08:00
|
|
|
|
with the executable directive will be resolved in Semantic Analysis.
|
|
|
|
|
|
|
|
|
|
When the backtracking parser can not identify the associated code blocks,
|
|
|
|
|
the parse tree will be rewritten later in the Semantics Analysis.
|
|
|
|
|
|
|
|
|
|
#### Stand-alone Directives
|
|
|
|
|
|
|
|
|
|
An OpenMP executable directive that has no associated user code
|
|
|
|
|
except for that which appears in clauses in the directive.
|
|
|
|
|
|
|
|
|
|
List of existing ones:
|
|
|
|
|
* taskyield
|
|
|
|
|
* barrier
|
|
|
|
|
* taskwait
|
|
|
|
|
* target enter data
|
|
|
|
|
* target exit data
|
|
|
|
|
* target update
|
|
|
|
|
* ordered
|
|
|
|
|
* flush
|
|
|
|
|
* cancel
|
|
|
|
|
* cancellation point
|
|
|
|
|
|
2019-08-28 09:12:50 +08:00
|
|
|
|
A higher-level class is created for each category
|
2019-08-28 05:38:48 +08:00
|
|
|
|
which contains directives listed above that share a similar structure:
|
|
|
|
|
* OpenMPSimpleStandaloneConstruct
|
|
|
|
|
(taskyield, barrier, taskwait,
|
|
|
|
|
target enter/exit data, target update, ordered)
|
|
|
|
|
* OpenMPFlushConstruct
|
|
|
|
|
* OpenMPCancelConstruct
|
|
|
|
|
* OpenMPCancellationPointConstruct
|
|
|
|
|
|
|
|
|
|
A top-level class, `OpenMPStandaloneConstruct`,
|
|
|
|
|
holds all four of the node types as discriminated unions
|
|
|
|
|
along with the source provenance for the entire directive.
|
|
|
|
|
Also, each parser node for the stand-alone directive saves
|
|
|
|
|
the source provenance for the directive name itself.
|
|
|
|
|
|
|
|
|
|
### Clauses
|
|
|
|
|
|
|
|
|
|
Each clause represented as a distinct class in `parse-tree.h`.
|
2019-08-28 09:12:50 +08:00
|
|
|
|
A top-level class, `OmpClause`,
|
|
|
|
|
includes all the clauses as discriminated unions.
|
|
|
|
|
The parser node for `OmpClause` saves the source provenance
|
|
|
|
|
for the entire clause.
|
2019-08-28 05:38:48 +08:00
|
|
|
|
|
2019-08-28 09:12:50 +08:00
|
|
|
|
All the `Names` or `Designators` associated
|
2019-08-28 05:38:48 +08:00
|
|
|
|
with the clauses will be resolved in Semantic Analysis.
|
|
|
|
|
|
|
|
|
|
Note that the backtracking parser will not validate
|
|
|
|
|
that the list of clauses associated
|
|
|
|
|
with a directive is valid other than to make sure they are well-formed.
|
|
|
|
|
In particular,
|
|
|
|
|
the parser does not check that
|
|
|
|
|
the association between directive and clauses is correct
|
|
|
|
|
nor check that the values in the directives or clauses are correct.
|
|
|
|
|
These checks are deferred to later phases of semantics to simplify the parser.
|
|
|
|
|
|
|
|
|
|
## Symbol Table Extensions for OpenMP
|
|
|
|
|
|
|
|
|
|
Name resolution can be impacted by the OpenMP code.
|
|
|
|
|
In addition to the regular steps to do the name resolution,
|
|
|
|
|
new scopes and symbols may need to be created
|
|
|
|
|
when encountering certain OpenMP constructs.
|
|
|
|
|
This section describes the extensions
|
|
|
|
|
for OpenMP during Symbol Table construction.
|
|
|
|
|
|
|
|
|
|
OpenMP uses the fork-join model of parallel execution and
|
|
|
|
|
all OpenMP threads have access to
|
|
|
|
|
a _shared_ memory place to store and retrieve variables
|
|
|
|
|
but each thread can also have access to
|
|
|
|
|
its _threadprivate_ memory that must not be accessed by other threads.
|
|
|
|
|
|
|
|
|
|
For the directives and clauses that can control the data environments,
|
|
|
|
|
compiler needs to determine two kinds of _access_
|
|
|
|
|
to variables used in the directive’s associated structured block:
|
|
|
|
|
**shared** and **private**.
|
|
|
|
|
Each variable referenced in the structured block
|
2019-08-28 09:12:50 +08:00
|
|
|
|
has an original variable immediately outside of the OpenMP constructs.
|
|
|
|
|
Reference to a shared variable in the structured block
|
2019-08-28 05:38:48 +08:00
|
|
|
|
becomes a reference to the original variable.
|
|
|
|
|
However, each private variable referenced in the structured block,
|
|
|
|
|
a new version of the original variable (of the same type and size)
|
|
|
|
|
will be created in the threadprivate memory.
|
|
|
|
|
|
|
|
|
|
There are exceptions that directives/clauses
|
|
|
|
|
need to create a new `Symbol` without creating a new `Scope`,
|
|
|
|
|
but in general,
|
|
|
|
|
when encountering each of the data environment controlling directives
|
|
|
|
|
(discussed in the following sections),
|
|
|
|
|
a new `Scope` will be created.
|
|
|
|
|
For each private variable referenced in the structured block,
|
|
|
|
|
a new `Symbol` is created out of the original variable
|
|
|
|
|
and the new `Symbol` is associated
|
|
|
|
|
with original variable’s `Symbol` via `HostAssocDetails`.
|
|
|
|
|
A new set of OpenMP specific flags are added
|
|
|
|
|
into `Flag` class in `symbol.h` to indicate the types of
|
|
|
|
|
associations,
|
|
|
|
|
data-sharing attributes,
|
|
|
|
|
and data-mapping attributes
|
|
|
|
|
in the OpenMP data environments.
|
|
|
|
|
|
|
|
|
|
### New Symbol without new Scope
|
|
|
|
|
|
|
|
|
|
OpenMP directives that require new `Symbol` to be created
|
|
|
|
|
but not new `Scope` are listed in the following table
|
|
|
|
|
in terms of the Symbol Table extensions for OpenMP:
|
|
|
|
|
|
|
|
|
|
<table>
|
|
|
|
|
<tr>
|
|
|
|
|
<td rowspan="2" colspan="2" >Directives/Clauses
|
|
|
|
|
</td>
|
|
|
|
|
<td rowspan="2" >Create New
|
|
|
|
|
<p>
|
|
|
|
|
Symbol
|
|
|
|
|
<p>
|
|
|
|
|
w/
|
|
|
|
|
</td>
|
|
|
|
|
<td colspan="2" >Add Flag
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>on Symbol of
|
|
|
|
|
</td>
|
|
|
|
|
<td>Flag
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td rowspan="4" >Declarative Directives
|
|
|
|
|
</td>
|
|
|
|
|
<td>declare simd [(proc-name)]
|
|
|
|
|
</td>
|
|
|
|
|
<td>-
|
|
|
|
|
</td>
|
2019-08-28 09:12:50 +08:00
|
|
|
|
<td>The name of the enclosing function, subroutine, or interface body
|
|
|
|
|
to which it applies, or proc-name
|
2019-08-28 05:38:48 +08:00
|
|
|
|
</td>
|
|
|
|
|
<td>OmpDeclareSimd
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>declare target
|
|
|
|
|
</td>
|
|
|
|
|
<td>-
|
|
|
|
|
</td>
|
2019-08-28 09:12:50 +08:00
|
|
|
|
<td>The name of the enclosing function, subroutine, or interface body
|
|
|
|
|
to which it applies
|
2019-08-28 05:38:48 +08:00
|
|
|
|
</td>
|
|
|
|
|
<td>OmpDeclareTarget
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>threadprivate(list)
|
|
|
|
|
</td>
|
|
|
|
|
<td>-
|
|
|
|
|
</td>
|
|
|
|
|
<td>named variables and named common blocks
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpThreadPrivate
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>declare reduction
|
|
|
|
|
</td>
|
|
|
|
|
<td>*
|
|
|
|
|
</td>
|
|
|
|
|
<td>reduction-identifier
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpDeclareReduction
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Stand-alone directives
|
|
|
|
|
</td>
|
|
|
|
|
<td>flush
|
|
|
|
|
</td>
|
|
|
|
|
<td>-
|
|
|
|
|
</td>
|
|
|
|
|
<td>variable, array section or common block name
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpFlushed
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td colspan="2" >critical [(name)]
|
|
|
|
|
</td>
|
|
|
|
|
<td>-
|
|
|
|
|
</td>
|
|
|
|
|
<td>name (user-defined identifier)
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpCriticalLock
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td colspan="2" >if ([ directive-name-modifier :] scalar-logical-expr)
|
|
|
|
|
</td>
|
|
|
|
|
<td>-
|
|
|
|
|
</td>
|
|
|
|
|
<td>directive-name-modifier
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpIfSpecified
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- No Action
|
|
|
|
|
|
|
|
|
|
* Discussed in “Module File Extensions for OpenMP” section
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### New Symbol with new Scope
|
|
|
|
|
|
|
|
|
|
For the following OpenMP regions:
|
|
|
|
|
|
|
|
|
|
* `target` regions
|
|
|
|
|
* `teams` regions
|
|
|
|
|
* `parallel` regions
|
|
|
|
|
* `simd` regions
|
|
|
|
|
* task generating regions (created by `task` or `taskloop` constructs)
|
|
|
|
|
* worksharing regions
|
|
|
|
|
(created by `do`, `sections`, `single`, or `workshare` constructs)
|
|
|
|
|
|
|
|
|
|
A new `Scope` will be created
|
|
|
|
|
when encountering the above OpenMP constructs
|
|
|
|
|
to ensure the correct data environment during the Code Generation.
|
|
|
|
|
To determine whether a variable referenced in these regions
|
|
|
|
|
needs the creation of a new `Symbol`,
|
|
|
|
|
all the data-sharing attribute rules
|
|
|
|
|
described in OpenMP Spec [2.15.1] apply during the Name Resolution.
|
|
|
|
|
The available data-sharing attributes are:
|
|
|
|
|
**_shared_**,
|
|
|
|
|
**_private_**,
|
|
|
|
|
**_linear_**,
|
|
|
|
|
**_firstprivate_**,
|
|
|
|
|
and **_lastprivate_**.
|
|
|
|
|
The attribute is represented as `Flag` in the `Symbol` object.
|
|
|
|
|
|
|
|
|
|
More details are listed in the following table:
|
|
|
|
|
|
|
|
|
|
<table>
|
|
|
|
|
<tr>
|
|
|
|
|
<td rowspan="2" >Attribute
|
|
|
|
|
</td>
|
|
|
|
|
<td rowspan="2" >Create New Symbol
|
|
|
|
|
</td>
|
|
|
|
|
<td colspan="2" >Add Flag
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>on Symbol of
|
|
|
|
|
</td>
|
|
|
|
|
<td>Flag
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>shared
|
|
|
|
|
</td>
|
|
|
|
|
<td>No
|
|
|
|
|
</td>
|
|
|
|
|
<td>Original variable
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpShared
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>private
|
|
|
|
|
</td>
|
|
|
|
|
<td>Yes
|
|
|
|
|
</td>
|
|
|
|
|
<td>New Symbol
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpPrivate
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>linear
|
|
|
|
|
</td>
|
|
|
|
|
<td>Yes
|
|
|
|
|
</td>
|
|
|
|
|
<td>New Symbol
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpLinear
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>firstprivate
|
|
|
|
|
</td>
|
|
|
|
|
<td>Yes
|
|
|
|
|
</td>
|
|
|
|
|
<td>New Symbol
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpFirstPrivate
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>lastprivate
|
|
|
|
|
</td>
|
|
|
|
|
<td>Yes
|
|
|
|
|
</td>
|
|
|
|
|
<td>New Symbol
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpLastPrivate
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
To determine the right data-sharing attribute,
|
|
|
|
|
OpenMP defines that the data-sharing attributes
|
|
|
|
|
of variables that are referenced in a construct can be
|
|
|
|
|
_predetermined_, _explicitly determined_, or _implicitly determined_.
|
|
|
|
|
|
|
|
|
|
#### Predetermined data-sharing attributes
|
|
|
|
|
|
|
|
|
|
* Assumed-size arrays are **shared**
|
|
|
|
|
* The loop iteration variable(s)
|
|
|
|
|
in the associated _do-loop(s)_ of a
|
|
|
|
|
_do_,
|
|
|
|
|
_parallel do_,
|
|
|
|
|
_taskloop_,
|
|
|
|
|
or _distributeconstruct_
|
|
|
|
|
is (are) **private**
|
|
|
|
|
* A loop iteration variable
|
|
|
|
|
for a sequential loop in a _parallel_ or task generating construct
|
|
|
|
|
is **private** in the innermost such construct that encloses the loop
|
|
|
|
|
* Implied-do indices and _forall_ indices are **private**
|
|
|
|
|
* The loop iteration variable in the associated _do-loop_
|
2019-08-31 02:22:13 +08:00
|
|
|
|
of a _simd_ construct with just one associated _do-loop_
|
2019-08-28 05:38:48 +08:00
|
|
|
|
is **linear** with a linear-step
|
|
|
|
|
that is the increment of the associated _do-loop_
|
|
|
|
|
* The loop iteration variables in the associated _do-loop(s)_ of a _simd_
|
|
|
|
|
construct with multiple associated _do-loop(s)_ are **lastprivate**
|
|
|
|
|
|
|
|
|
|
#### Explicitly determined data-sharing attributes
|
|
|
|
|
|
|
|
|
|
Variables with _explicitly determined_ data-sharing attributes are:
|
|
|
|
|
|
|
|
|
|
* Variables are referenced in a given construct
|
|
|
|
|
* Variables are listed in a data-sharing attribute clause on the construct.
|
|
|
|
|
|
|
|
|
|
The data-sharing attribute clauses are:
|
|
|
|
|
* _default_ clause
|
|
|
|
|
(discussed in “Implicitly determined data-sharing attributes”)
|
|
|
|
|
* _shared_ clause
|
|
|
|
|
* _private_ clause
|
|
|
|
|
* _linear_ clause
|
|
|
|
|
* _firstprivate_ clause
|
|
|
|
|
* _lastprivate_ clause
|
|
|
|
|
* _reduction_ clause
|
|
|
|
|
(new `Symbol` created with the flag `OmpReduction` set)
|
|
|
|
|
|
|
|
|
|
Note that variables with _predetermined_ data-sharing attributes
|
|
|
|
|
may not be listed (with exceptions) in data-sharing attribute clauses.
|
|
|
|
|
|
|
|
|
|
#### Implicitly determined data-sharing attributes
|
|
|
|
|
|
|
|
|
|
Variables with implicitly determined data-sharing attributes are:
|
|
|
|
|
|
|
|
|
|
* Variables are referenced in a given construct
|
|
|
|
|
* Variables do not have _predetermined_ data-sharing attributes
|
|
|
|
|
* Variables are not listed in a data-sharing attribute clause
|
|
|
|
|
on the construct.
|
|
|
|
|
|
|
|
|
|
Rules for variables with _implicitly determined_ data-sharing attributes:
|
|
|
|
|
|
|
|
|
|
* In a _parallel_ construct, if no _default_ clause is present,
|
|
|
|
|
these variables are **shared**
|
|
|
|
|
* In a task generating construct,
|
|
|
|
|
if no _default_ clause is present,
|
|
|
|
|
a variable for which the data-sharing attribute
|
|
|
|
|
is not determined by the rules above
|
|
|
|
|
and that in the enclosing context is determined
|
|
|
|
|
to be shared by all implicit tasks
|
|
|
|
|
bound to the current team is **shared**
|
|
|
|
|
* In a _target_ construct,
|
|
|
|
|
variables that are not mapped after applying data-mapping attribute rules
|
|
|
|
|
(discussed later) are **firstprivate**
|
|
|
|
|
* In an orphaned task generating construct,
|
|
|
|
|
if no _default_ clause is present, dummy arguments are **firstprivate**
|
|
|
|
|
* In a task generating construct, if no _default_ clause is present,
|
|
|
|
|
a variable for which the data-sharing attribute is not determined
|
|
|
|
|
by the rules above is **firstprivate**
|
2019-08-31 02:22:13 +08:00
|
|
|
|
* For constructs other than task generating constructs or _target_ constructs,
|
2019-08-28 05:38:48 +08:00
|
|
|
|
if no _default_ clause is present,
|
|
|
|
|
these variables reference the variables with the same names
|
|
|
|
|
that exist in the enclosing context
|
|
|
|
|
* In a _parallel_, _teams_, or task generating construct,
|
|
|
|
|
the data-sharing attributes of these variables are determined
|
2019-08-31 02:22:13 +08:00
|
|
|
|
by the _default_ clause, if present:
|
2019-08-28 05:38:48 +08:00
|
|
|
|
* _default(shared)_
|
|
|
|
|
clause causes all variables referenced in the construct
|
|
|
|
|
that have _implicitly determined_ data-sharing attributes
|
|
|
|
|
to be **shared**
|
|
|
|
|
* _default(private)_
|
|
|
|
|
clause causes all variables referenced in the construct
|
|
|
|
|
that have _implicitly determined_ data-sharing attributes
|
|
|
|
|
to be **private**
|
|
|
|
|
* _default(firstprivate)_
|
|
|
|
|
clause causes all variables referenced in the construct
|
|
|
|
|
that have _implicitly determined_ data-sharing attributes
|
|
|
|
|
to be **firstprivate**
|
|
|
|
|
* _default(none)_
|
|
|
|
|
clause requires that each variable
|
|
|
|
|
that is referenced in the construct,
|
|
|
|
|
and that does not have a _predetermined_ data-sharing attribute,
|
|
|
|
|
must have its data-sharing attribute _explicitly determined_
|
|
|
|
|
by being listed in a data-sharing attribute clause
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Data-mapping Attribute
|
|
|
|
|
|
|
|
|
|
When encountering the _target data_ and _target_ directives,
|
|
|
|
|
the data-mapping attributes of any variable referenced in a target region
|
|
|
|
|
will be determined and represented as `Flag` in the `Symbol` object
|
|
|
|
|
of the variable.
|
|
|
|
|
No `Symbol` or `Scope` will be created.
|
|
|
|
|
|
|
|
|
|
The basic steps to determine the data-mapping attribute are:
|
|
|
|
|
|
|
|
|
|
1. If _map_ clause is present,
|
|
|
|
|
the data-mapping attribute is determined by the _map-type_
|
|
|
|
|
on the clause and its corresponding `Flag` are listed below:
|
|
|
|
|
|
|
|
|
|
<table>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>
|
|
|
|
|
data-mapping attribute
|
|
|
|
|
</td>
|
|
|
|
|
<td>Flag
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>to
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpMapTo
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>from
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpMapFrom
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
2019-08-31 02:22:13 +08:00
|
|
|
|
<td>tofrom
|
2019-08-28 05:38:48 +08:00
|
|
|
|
(default if map-type is not present)
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpMapTo & OmpMapFrom
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>alloc
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpMapAlloc
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>release
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpMapRelease
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>delete
|
|
|
|
|
</td>
|
|
|
|
|
<td>OmpMapDelete
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
2. Otherwise, the following data-mapping rules apply
|
|
|
|
|
for variables referenced in a _target_ construct
|
|
|
|
|
that are _not_ declared in the construct and
|
|
|
|
|
do not appear in data-sharing attribute or map clauses:
|
2019-08-28 09:12:50 +08:00
|
|
|
|
* If a variable appears in a _to_ or _link_ clause
|
|
|
|
|
on a _declare target_ directive then it is treated
|
|
|
|
|
as if it had appeared in a _map_ clause with a _map-type_ of **tofrom**
|
2019-08-28 05:38:48 +08:00
|
|
|
|
3. Otherwise, the following implicit data-mapping attribute rules apply:
|
|
|
|
|
* If a _defaultmap(tofrom:scalar)_ clause is _not_ present
|
|
|
|
|
then a scalar variable is not mapped,
|
|
|
|
|
but instead has an implicit data-sharing attribute of **firstprivate**
|
|
|
|
|
* If a _defaultmap(tofrom:scalar)_ clause is present
|
|
|
|
|
then a scalar variable is treated as if it had appeared
|
|
|
|
|
in a map clause with a map-type of **tofrom**
|
|
|
|
|
* If a variable is not a scalar
|
|
|
|
|
then it is treated as if it had appeared in a map clause
|
|
|
|
|
with a _map-type_ of **tofrom**
|
|
|
|
|
|
2019-08-28 09:12:50 +08:00
|
|
|
|
After the completion of the Name Resolution phase,
|
|
|
|
|
all the data-sharing or data-mapping attributes marked for the `Symbols`
|
|
|
|
|
may be used later in the Semantics Analysis and in the Code Generation.
|
2019-08-28 05:38:48 +08:00
|
|
|
|
|
|
|
|
|
## Module File Extensions for OpenMP
|
|
|
|
|
|
2019-08-28 09:12:50 +08:00
|
|
|
|
After the successful compilation of modules and submodules
|
|
|
|
|
that may contain the following Declarative Directives,
|
|
|
|
|
the entire directive starting from `!$OMP` needs to be written out
|
|
|
|
|
into `.mod` files in their corresponding Specification Part:
|
2019-08-28 05:38:48 +08:00
|
|
|
|
|
|
|
|
|
* _declare simd_ or _declare target_
|
|
|
|
|
|
|
|
|
|
In the “New Symbol without new Scope” section,
|
|
|
|
|
we described that when encountering these two declarative directives,
|
|
|
|
|
new `Flag` will be applied to the Symbol of the name of
|
|
|
|
|
the enclosing function, subroutine, or interface body to
|
|
|
|
|
which it applies, or proc-name.
|
|
|
|
|
This `Flag` should be part of the API information
|
|
|
|
|
for the given subroutine or function
|
|
|
|
|
|
|
|
|
|
* _declare reduction_
|
|
|
|
|
|
|
|
|
|
The _reduction-identifier_ in this directive
|
|
|
|
|
can be use-associated or host-associated.
|
|
|
|
|
However, it will not act like other Symbols
|
|
|
|
|
because user may have a reduction name
|
|
|
|
|
that is the same as a Fortran entity name in the same scope.
|
|
|
|
|
Therefore a specific data structure needs to be created
|
|
|
|
|
to save the _reduction-identifier_ information
|
|
|
|
|
in the Scope and this directive needs to be written into `.mod` files
|
|
|
|
|
|
|
|
|
|
## Phases of OpenMP Analysis
|
|
|
|
|
|
|
|
|
|
1. Create the parse tree for OpenMP
|
2019-08-31 02:22:13 +08:00
|
|
|
|
1. Add types for directives and clauses
|
2019-08-28 05:38:48 +08:00
|
|
|
|
1. Add type(s) that will be used for directives
|
|
|
|
|
2. Add type(s) that will be used for clauses
|
|
|
|
|
3. Add other types, e.g. wrappers or other containers
|
|
|
|
|
4. Use std::variant to encapsulate meaningful types
|
|
|
|
|
2. Implemented in the parser for OpenMP (openmp-grammar.h)
|
|
|
|
|
2. Create canonical nesting
|
|
|
|
|
1. Restructure parse tree to reflect the association
|
|
|
|
|
of directives and stmts
|
|
|
|
|
1. Associate `OpenMPLoopConstruct`
|
|
|
|
|
with `DoConstruct` and `OpenMPEndLoopDirective`
|
|
|
|
|
1. Investigate, and perhaps reuse,
|
|
|
|
|
the algorithm used to restructure do-loops
|
|
|
|
|
2. Add a pass near the code that restructures do-loops;
|
|
|
|
|
but do not extend the code that handles do-loop for OpenMP;
|
|
|
|
|
keep this code separate.
|
|
|
|
|
3. Report errors that prevent restructuring
|
|
|
|
|
(e.g. loop directive not followed by loop)
|
|
|
|
|
We should abort in case of errors
|
|
|
|
|
because there is no point to perform further checks
|
|
|
|
|
if it is not a legal OpenMP construct
|
|
|
|
|
3. Validate the structured-block
|
|
|
|
|
1. Structured-block is a block of executable statements
|
|
|
|
|
1. Single entry and single exit
|
|
|
|
|
1. Access to the structured block must not be the result of a branch
|
|
|
|
|
1. The point of exit cannot be a branch out of the structured block
|
|
|
|
|
4. Check that directive and clause combinations are legal
|
|
|
|
|
1. Begin and End directive should match
|
|
|
|
|
1. Simply check that the clauses are allowed by the directives
|
|
|
|
|
1. Write as a separate pass for simplicity and correctness of the parse tree
|
|
|
|
|
5. Write parse tree tests
|
|
|
|
|
1. At this point, the parse tree should be perfectly formed
|
|
|
|
|
1. Write tests that check for correct form and provenance information
|
|
|
|
|
1. Write tests for errors that can occur during the restructuring
|
|
|
|
|
6. Scope, symbol tables, and name resolution
|
|
|
|
|
1. Update the existing code to handle names and scopes introduced by OpenMP
|
|
|
|
|
1. Write tests to make sure names are properly implemented
|
|
|
|
|
7. Check semantics that is specific to each directive
|
|
|
|
|
1. Validate the directive and its clauses
|
|
|
|
|
1. Some clause checks require the result of name resolution,
|
|
|
|
|
i.e. “A list item may appear in a _linear_ or _firstprivate_ clause
|
|
|
|
|
but not both.”
|
|
|
|
|
1. TBD:
|
|
|
|
|
Validate the nested statement for legality in the scope of the directive
|
|
|
|
|
1. Check the nesting of regions [OpenMP 4.5 spec 2.17]
|
|
|
|
|
8. Module file utilities
|
|
|
|
|
1. Write necessary OpenMP declarative directives to `.mod` files
|
|
|
|
|
2. Update the existing code
|
|
|
|
|
to read available OpenMP directives from the `.mod` files
|