Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 25 additions & 23 deletions flang/docs/Directives.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!--===- docs/Directives.md
<!--===- docs/Directives.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

-->

# Compiler directives supported by Flang
Expand All @@ -12,16 +12,18 @@ A list of non-standard directives supported by Flang

* `!dir$ fixed` and `!dir$ free` select Fortran source forms. Their effect
persists to the end of the current source file.
* `!dir$ ignore_tkr [[(TKRDMAC)] dummy-arg-name]...` in an interface definition
* `!dir$ ignore_tkr [[(TKRDMACP)] dummy-arg-name]...` in an interface definition
disables some semantic checks at call sites for the actual arguments that
correspond to some named dummy arguments (or all of them, by default).
The directive allow actual arguments that would otherwise be diagnosed
as incompatible in type (T), kind (K), rank (R), CUDA device (D), or
managed (M) status. The letter (A) is a shorthand for all of these,
and is the default when no letters appear. The letter (C) checks for
contiguity for example allowing an element of an assumed-shape array to be
passed as a dummy argument. For example, if one wanted to call a "set all
bytes to zero" utility that could be applied to arrays of any type or rank:
correspond to some named dummy arguments (or all of them, by default). The
directive allow actual arguments that would otherwise be diagnosed as
incompatible in type (T), kind (K), rank (R), CUDA device (D), or managed (M)
status. The letter (A) is a shorthand for (TKRDM), and is the default when no
letters appear. The letter (C) checks for contiguity, for example allowing an
element of an assumed-shape array to be passed as a dummy argument. The
letter (P) ignores pointer and allocatable matching, so that one can pass an
allocatable array to routine with pointer array argument and vice versa. For
example, if one wanted to call a "set all bytes to zero" utility that could
be applied to arrays of any type or rank:
```
interface
subroutine clear(arr,bytes)
Expand All @@ -46,27 +48,27 @@ A list of non-standard directives supported by Flang
unroll the loop. Some compilers accept an optional `=` before the `n` when `n`
is present in the directive. Flang does not.
* `!dir$ unroll_and_jam [N]` control how many times a loop should be unrolled and
jammed. It must be placed immediately before a loop that follows. `N` is an optional
integer that specifying the unrolling factor. When `N` is `0` or `1`, the loop
jammed. It must be placed immediately before a loop that follows. `N` is an optional
integer that specifying the unrolling factor. When `N` is `0` or `1`, the loop
should not be unrolled at all. If `N` is omitted the optimizer will
selects the number of times to unroll the loop.
* `!dir$ novector` disabling vectorization on the following loop.
* `!dir$ nounroll` disabling unrolling on the following loop.
* `!dir$ nounroll_and_jam` disabling unrolling and jamming on the following loop.
* `!dir$ inline` instructs the compiler to attempt to inline the called routines if the
directive is specified before a call statement or all call statements within the loop
body if specified before a DO LOOP or all function references if specified before an
* `!dir$ inline` instructs the compiler to attempt to inline the called routines if the
directive is specified before a call statement or all call statements within the loop
body if specified before a DO LOOP or all function references if specified before an
assignment statement.
* `!dir$ forceinline` works in the same way as the `inline` directive, but it forces
* `!dir$ forceinline` works in the same way as the `inline` directive, but it forces
inlining by the compiler on a function call statement.
* `!dir$ noinline` works in the same way as the `inline` directive, but prevents
* `!dir$ noinline` works in the same way as the `inline` directive, but prevents
any attempt of inlining by the compiler on a function call statement.

# Directive Details

## Introduction
Directives are commonly used in Fortran programs to specify additional actions
to be performed by the compiler. The directives are always specified with the
Directives are commonly used in Fortran programs to specify additional actions
to be performed by the compiler. The directives are always specified with the
`!dir$` or `cdir$` prefix.

## Loop Directives
Expand Down Expand Up @@ -97,7 +99,7 @@ check that that construct matches the expected construct for the directive.
Skipping other intermediate directives allows multiple directives to appear on
the same construct.

## Lowering
## Lowering
Evaluation is extended with a new field called dirs for representing directives
associated with that Evaluation. When lowering loop directives, the associated
Do Loop's evaluation is found and the directive is added to it. This information
Expand All @@ -109,7 +111,7 @@ about the loop. For example, the `llvm.loop.vectorize.enable` metadata informs
the optimizer that a loop can be vectorized without considering its cost-model.
This attribute is added to the loop condition branch.

### Representation in MLIR
### Representation in MLIR
The MLIR LLVM dialect models this by an attribute called LoopAnnotation
Attribute. The attribute can be added to the latch of the loop in the cf
dialect and is then carried through lowering to the LLVM dialect.
Expand Down
3 changes: 2 additions & 1 deletion flang/include/flang/Support/Fortran.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ ENUM_CLASS(IgnoreTKR,
Rank, // R - don't check ranks
Device, // D - don't check host/device residence
Managed, // M - don't check managed storage
Contiguous) // C - don't check for storage sequence association with a
Contiguous, // C - don't check for storage sequence association with a
// potentially non-contiguous object
Pointer) // P - ignore pointer and allocatable matching
using IgnoreTKRSet = EnumSet<IgnoreTKR, 8>;
// IGNORE_TKR(A) = IGNORE_TKR(TKRDM)
static constexpr IgnoreTKRSet ignoreTKRAll{IgnoreTKR::Type, IgnoreTKR::Kind,
Expand Down
6 changes: 4 additions & 2 deletions flang/lib/Semantics/check-call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
dummyName);
}
// INTENT(OUT) and INTENT(IN OUT) cases are caught elsewhere
} else {
} else if (!actualIsAllocatable &&
!dummy.ignoreTKR.test(common::IgnoreTKR::Pointer)) {
messages.Say(
"ALLOCATABLE %s must be associated with an ALLOCATABLE actual argument"_err_en_US,
dummyName);
Expand All @@ -929,7 +930,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
dummy, actual, *scope,
/*isAssumedRank=*/dummyIsAssumedRank, actualIsPointer);
}
} else if (!actualIsPointer) {
} else if (!actualIsPointer &&
!dummy.ignoreTKR.test(common::IgnoreTKR::Pointer)) {
messages.Say(
"Actual argument associated with POINTER %s must also be POINTER unless INTENT(IN)"_err_en_US,
dummyName);
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Semantics/check-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,8 @@ void CheckHelper::CheckObjectEntity(
"!DIR$ IGNORE_TKR(R) may not apply in an ELEMENTAL procedure"_err_en_US);
}
if (IsPassedViaDescriptor(symbol)) {
if (IsAllocatableOrObjectPointer(&symbol)) {
if (IsAllocatableOrObjectPointer(&symbol) &&
!ignoreTKR.test(common::IgnoreTKR::Pointer)) {
if (inExplicitExternalInterface) {
Warn(common::UsageWarning::IgnoreTKRUsage,
"!DIR$ IGNORE_TKR should not apply to an allocatable or pointer"_warn_en_US);
Expand Down
3 changes: 3 additions & 0 deletions flang/lib/Semantics/mod-file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,9 @@ void ModFileWriter::PutObjectEntity(
case common::IgnoreTKR::Contiguous:
os << 'c';
break;
case common::IgnoreTKR::Pointer:
os << 'p';
break;
}
});
os << ") " << symbol.name() << '\n';
Expand Down
3 changes: 3 additions & 0 deletions flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10109,6 +10109,9 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {
case 'c':
set.set(common::IgnoreTKR::Contiguous);
break;
case 'p':
set.set(common::IgnoreTKR::Pointer);
break;
case 'a':
set = common::ignoreTKRAll;
break;
Expand Down
3 changes: 3 additions & 0 deletions flang/lib/Support/Fortran.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ std::string AsFortran(IgnoreTKRSet tkr) {
if (tkr.test(IgnoreTKR::Contiguous)) {
result += 'C';
}
if (tkr.test(IgnoreTKR::Pointer)) {
result += 'P';
}
return result;
}

Expand Down
26 changes: 26 additions & 0 deletions flang/test/Semantics/ignore_tkr04.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
! Tests for ignore_tkr(p)
module ignore_tkr_4_m
interface
subroutine s(a)
real, pointer :: a(:)
!dir$ ignore_tkr(p) a
end subroutine
subroutine s1(a)
real, allocatable :: a(:)
!dir$ ignore_tkr(p) a
end subroutine
end interface
end module
program t
use ignore_tkr_4_m
real, allocatable :: x(:)
real, pointer :: x1(:)
call s(x)
!CHECK-NOT: error
!CHECK-NOT: warning
call s1(x1)
!CHECK-NOT: error
!CHECK-NOT: warning
end