This implements the RANK clause per the Fortran 2023 Standard. This
includes both the parsing/semantics and un-parsing functionality. It is
a fairly straight-forward change.
An executable test was added that tests the examples from the Fortran
2023 What's New document.
check-flang, check-flang-rt, and llvm-lit tests have been executed
against this change.
---------
Co-authored-by: Kevin Wyatt <kwyatt@hpe.com>
Follow-up to PR175211.
There are still a few AST nodes that don't have any of the standard
traits (Wrapper/Tuple/etc). Because of that they require special
handling in the parse tree visitor.
Convert a subset of these nodes to the typical format, and remove the
special cases from the parse tree visitor.
The members of these nodes were frequently used, so instead of
extracting them by hand each time use helper member functions to access
them.
Follow-up to PR175211.
There are still a few AST nodes that don't have any of the standard
traits (Wrapper/Tuple/etc). Because of that they require special
handling in the parse tree visitor.
Convert a subset of these nodes to the typical format, and remove the
special cases from the parse tree visitor.
There are quite a few AST nodes that don't have any of the standard
traits (Wrapper/Tuple/etc). Because of that they require special
handling in the parse tree visitor.
Convert a subset of these nodes to the typical format, and remove the
special cases from the parse tree visitor.
A bad I/O control specification ("NML=123" in this case) triggers an
assertion when parsing fails but emits no error message. The message was
lost when combining failed alternative parse states. Make
CombineFailedParses() take more care to not discard messages; then also
strengthen I/O control specification error recovery so that the original
test case doesn't just elicit a confusing complaint about a missing
expected "*" at the site of the "NML" keyword.
Fixes https://github.com/llvm/llvm-project/issues/173522.
In OpenMP 6.0 a subset of the dependence types is also used in the
`depinfo-modifier` on INIT clause. Make the enum be a common type to
avoid defining separate enum types with mostly identical members.
Use the name `OmpDependenceKind` because the other obvious candidate,
OmpDependenceType, used to be a modifier name in older OpenMP specs.
This includes `FR(...)` for foreign runtime identifiers and `ATTR(...)`
for extensions. Do not store string runtime ids as character literals in
the AST. Use parser::Expr instead, since lowering would require
evaluate::Expr for these ids, and we get evaluate::Expr from
parser::Expr automatically.
Use OpenMP 6.0 naming for AST nodes (since it's the "current" one).
The convention is to change spelling from snake_case to UpperCamel, and
use the result as a stem in derived names, e.g.
- spelling is "some_clause" -> stem is SomeClause
- spelling is "someclause" -> stem is Someclause
Member of the OmpClause variant is <stem> itself, e.g. Looprange as in
parser::OmpClause::Looprange.
Specific clause class name is Omp<stem>Clause, e.g. OmpLooprangeClause.
Add two more AST nodes, one for a misplaced end-directive, and one for
an invalid string following the OpenMP sentinel (e.g. "!$OMP XYZ").
Emit error messages when either node is encountered in semantic
analysis.
Instead of storing a variant with specific types, store parser::Block as
the body. Add two access functions to make the traversal of the nest
simpler.
This will allow storing loop-nest sequences in the future.
This directive tells the compiler to ignore vector dependencies in the
following loop and it must be placed before a `do loop`.
Sometimes the compiler may not have sufficient information to decide
whether a particular loop is vectorizable due to potential dependencies
between iterations and the directive is here to tell to the compiler
that vectorization is safe with `parallelAccesses` metadata.
This directive is also equivalent to `#pragma clang loop assume(safety)`
in C++
The "prescriptiveness" modifier has been replaced with
"fallback-modifier". The "fallback" value has been removed from the
"prescriptiveness" modifier.
Implementation details:
* Recognize prefetch directive in the parser as `!dir$ prefetch ...`
* Unparse the prefetch directive
* Add required tests
Details on the prefetch directive:
`!dir$ prefetch designator[, designator]...`, where the designator list
can be a variable or an array reference. This directive is used to
insert a hint to the code generator to prefetch instructions for
memory references.
The ALLOCATE directive has two forms:
- A declarative form with a standalone directive:
```
!$OMP ALLOCATE (variable-list-item...)
```
- An executable form that consists of several directives followed by an
ALLOCATE statement:
```
!$OMP ALLOCATE (variable-list-item...)
!$OMP ALLOCATE (variable-list-item...)
...
ALLOCATE (...)
```
The second form was deprecated in OpenMP 5.2 in favor of the ALLOCATORS
construct.
Since in the parse tree every type corresponding to a directive only
corresponds to a single directive, the executable form is represented by
a sequence of nested OmpAllocateDirectives, e.g.
```
!$OMP ALLOCATE(x)
!$OMP ALLOCATE(y)
ALLOCATE(x, y)
```
will become
```
OmpAllocateDirective
|- ALLOCATE(x) // begin directive
`- OmpAllocateDirective // block
|- ALLOCATE(y) // begin directive
`- ALLOCATE(x, y) // block
```
With this change all AST nodes for directives use
OmpDirectiveSpecification as the directive representation.
For ALLOCATORS and executable ALLOCATE first perform list item checks in
the context of an individual ALLOCATE clause or directive respectively,
then perform "global" checks, e.g. whether all list items are present on
the ALLOCATE statement.
These changes allowed to simplify the checks for presence on ALLOCATE
statement and the use of a predefined allocator.
Additionally, allow variable list item lists to be empty, add a test for
the related spec restriction.
This is a first step towards unifying OpenMPDeclarativeAllocate and
OpenMPExecutableAllocate into a single directive.
Consider OpenMP stylized expression to be a template to be instantiated
with a series of types listed on the containing directive (currently
DECLARE_REDUCTION). Create a series of instantiations in the parser,
allowing OpenMP special variables to be declared separately for each
type.
---------
Co-authored-by: Tom Eccles <tom.eccles@arm.com>
This patch adds the support of these two directives : `!dir$ inline` and
`!dir$ noinline`.
- `!dir$ noinline` tells to the compiler to not perform inlining on
specific function calls by adding the `noinline` metadata on the call.
- `!dir$ inline` tells to the compiler to attempt inlining on specific
function calls by adding the `inlinehint` metadata on the call.
- `!dir$ forceinline` tells to the compiler to always perfom inlining on
specific function calls by adding the `alwaysinline` metadata on the
call.
Currently, these directives can be placed before a `DO LOOP`, call
functions or assignments. Maybe other statements can be added in the
future if needed.
For the `inline` directive the correct name might be `forceinline` but
I'm not sure ?
Rename OmpTypeSpecifier to OmpTypeName, since it represents a type-name
list item. Also, OpenMP 6.0 introduced type-specifier with a different
meaning.
Rename OmpReductionCombiner to OmpCombinerExpression.
This change implements the fuse directive, `#pragma omp fuse`, as specified in the OpenMP 6.0, along with the `looprange` clause in clang.
This change also adds minimal stubs so flang keeps compiling (a full implementation in flang of this directive is still pending).
---------
Co-authored-by: Roger Ferrer Ibanez <roger.ferrer@bsc.es>
…sing
The DECLARE_VARIANT directive takes two names separated by a colon as an
argument: base-name:variant-name. Define OmpBaseVariantNames to
represent this, since no existing argument alternative matches it.
However, there is an issue. The syntax "name1:name2" can be the argument
to DECLARE_VARIANT (if both names are OmpObjects), but it can also be a
reduction-specifier if "name2" is a type. This conflict can only be
resolved once we know what the names are, which is after name resolution
has visited them. The problem is that name resolution has side-effects
that may be (practically) impossible to undo (e.g. creating new symbols,
emitting diagnostic messages).
To avoid this problem this PR makes the parsing of OmpArgument
directive- sensitive: when the directive is DECLARE_VARIANT, don't
attempt to parse a reduction-specifier, consider OmpBaseVariantNames
instead. Otherwise ignore OmpBaseVariantNames in favor of
reduction-specifier.
When the combiner contains an AssignmentStmt, the unparser for that will
emit a newline after the assignment. Don't let it do that, unparse the
assignment ourselves.
Instead of having a variant with specific AST nodes that can contain a
reduction specifier, simply store the OpenMPDeclarativeConstruct. It is
used to emit the source code directive when generating a module file,
and unparsing the top-level AST node will work just fine.
Since ODS doesn't store a list of OmpObjects (i.e. not as
OmpObjectList), some semantics-checking functions needed to be updated
to operate on a single object at a time.
…rective
This makes accessing directive components, such as directive name or the
list of clauses simpler and more uniform across different directives. It
also makes the parser simpler, since it reuses existing parsing
functionality.
The changes are scattered over a number of files, but they all share the
same nature:
- getting the begin/end directive from OpenMPLoopConstruct,
- getting the llvm::omp::Directive enum, and the source location,
- getting the clause list.
OpenMPBlockConstruct, somewhat confusingly, represents most but not all
block-associated constructs. It's derived from OmpBlockConstruct, as are
all the remaining block-associated constructs.
It does not correspond to any well-defined group of constructs. It's the
collection of constructs that don't have their own types (and those that
do have their own types do so for their own reasons).
Using the broader OmpBlockConstruct in type-based visitors won't cause
issues, because the specific overloads (for classes derived from it)
will always be preferred.
The ASSUME directive is block-associated and whether the end-directive
is optional or not depends on the form of the block. This is all taken
care of automatically since the AST node for ASSUME inherits from
OmpBlockConstruct.
See #90452. The old parse tree errors exploded to thousands of unhelpful
lines when there were multiple missing end directives.
Instead, allow a missing end directive in the parse tree then validate
that it is present during semantics (where the error messages are a lot
easier to control).