Skip to content

Commit edab721

Browse files
[flang] Implement IGNORE_TKR(P) (#165469)
Implemented IGNORE_TKR(P), which allows ignoring pointer and allocatable matching (can pass an allocatable array to routine with pointer array argument and vice versa). Updated documentation.
1 parent 57a0bf4 commit edab721

File tree

8 files changed

+68
-27
lines changed

8 files changed

+68
-27
lines changed

flang/docs/Directives.md

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
<!--===- docs/Directives.md
2-
1+
<!--===- docs/Directives.md
2+
33
Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
See https://llvm.org/LICENSE.txt for license information.
55
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6-
6+
77
-->
88

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

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

6567
# Directive Details
6668

6769
## Introduction
68-
Directives are commonly used in Fortran programs to specify additional actions
69-
to be performed by the compiler. The directives are always specified with the
70+
Directives are commonly used in Fortran programs to specify additional actions
71+
to be performed by the compiler. The directives are always specified with the
7072
`!dir$` or `cdir$` prefix.
7173

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

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

112-
### Representation in MLIR
114+
### Representation in MLIR
113115
The MLIR LLVM dialect models this by an attribute called LoopAnnotation
114116
Attribute. The attribute can be added to the latch of the loop in the cf
115117
dialect and is then carried through lowering to the LLVM dialect.

flang/include/flang/Support/Fortran.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ ENUM_CLASS(IgnoreTKR,
8686
Rank, // R - don't check ranks
8787
Device, // D - don't check host/device residence
8888
Managed, // M - don't check managed storage
89-
Contiguous) // C - don't check for storage sequence association with a
89+
Contiguous, // C - don't check for storage sequence association with a
9090
// potentially non-contiguous object
91+
Pointer) // P - ignore pointer and allocatable matching
9192
using IgnoreTKRSet = EnumSet<IgnoreTKR, 8>;
9293
// IGNORE_TKR(A) = IGNORE_TKR(TKRDM)
9394
static constexpr IgnoreTKRSet ignoreTKRAll{IgnoreTKR::Type, IgnoreTKR::Kind,

flang/lib/Semantics/check-call.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
914914
dummyName);
915915
}
916916
// INTENT(OUT) and INTENT(IN OUT) cases are caught elsewhere
917-
} else {
917+
} else if (!actualIsAllocatable &&
918+
!dummy.ignoreTKR.test(common::IgnoreTKR::Pointer)) {
918919
messages.Say(
919920
"ALLOCATABLE %s must be associated with an ALLOCATABLE actual argument"_err_en_US,
920921
dummyName);
@@ -929,7 +930,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
929930
dummy, actual, *scope,
930931
/*isAssumedRank=*/dummyIsAssumedRank, actualIsPointer);
931932
}
932-
} else if (!actualIsPointer) {
933+
} else if (!actualIsPointer &&
934+
!dummy.ignoreTKR.test(common::IgnoreTKR::Pointer)) {
933935
messages.Say(
934936
"Actual argument associated with POINTER %s must also be POINTER unless INTENT(IN)"_err_en_US,
935937
dummyName);

flang/lib/Semantics/check-declarations.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,8 @@ void CheckHelper::CheckObjectEntity(
949949
"!DIR$ IGNORE_TKR(R) may not apply in an ELEMENTAL procedure"_err_en_US);
950950
}
951951
if (IsPassedViaDescriptor(symbol)) {
952-
if (IsAllocatableOrObjectPointer(&symbol)) {
952+
if (IsAllocatableOrObjectPointer(&symbol) &&
953+
!ignoreTKR.test(common::IgnoreTKR::Pointer)) {
953954
if (inExplicitExternalInterface) {
954955
Warn(common::UsageWarning::IgnoreTKRUsage,
955956
"!DIR$ IGNORE_TKR should not apply to an allocatable or pointer"_warn_en_US);

flang/lib/Semantics/mod-file.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,9 @@ void ModFileWriter::PutObjectEntity(
10211021
case common::IgnoreTKR::Contiguous:
10221022
os << 'c';
10231023
break;
1024+
case common::IgnoreTKR::Pointer:
1025+
os << 'p';
1026+
break;
10241027
}
10251028
});
10261029
os << ") " << symbol.name() << '\n';

flang/lib/Semantics/resolve-names.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10109,6 +10109,9 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {
1010910109
case 'c':
1011010110
set.set(common::IgnoreTKR::Contiguous);
1011110111
break;
10112+
case 'p':
10113+
set.set(common::IgnoreTKR::Pointer);
10114+
break;
1011210115
case 'a':
1011310116
set = common::ignoreTKRAll;
1011410117
break;

flang/lib/Support/Fortran.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ std::string AsFortran(IgnoreTKRSet tkr) {
9595
if (tkr.test(IgnoreTKR::Contiguous)) {
9696
result += 'C';
9797
}
98+
if (tkr.test(IgnoreTKR::Pointer)) {
99+
result += 'P';
100+
}
98101
return result;
99102
}
100103

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
! Tests for ignore_tkr(p)
3+
module ignore_tkr_4_m
4+
interface
5+
subroutine s(a)
6+
real, pointer :: a(:)
7+
!dir$ ignore_tkr(p) a
8+
end subroutine
9+
subroutine s1(a)
10+
real, allocatable :: a(:)
11+
!dir$ ignore_tkr(p) a
12+
end subroutine
13+
end interface
14+
end module
15+
program t
16+
use ignore_tkr_4_m
17+
real, allocatable :: x(:)
18+
real, pointer :: x1(:)
19+
call s(x)
20+
!CHECK-NOT: error
21+
!CHECK-NOT: warning
22+
call s1(x1)
23+
!CHECK-NOT: error
24+
!CHECK-NOT: warning
25+
end
26+

0 commit comments

Comments
 (0)