Skip to content

Commit cf1f871

Browse files
[Flang] Add parser support for prefetch directive (#139702)
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.
1 parent b67796f commit cf1f871

File tree

8 files changed

+103
-1
lines changed

8 files changed

+103
-1
lines changed

flang/docs/Directives.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ A list of non-standard directives supported by Flang
5252
integer that specifying the unrolling factor. When `N` is `0` or `1`, the loop
5353
should not be unrolled at all. If `N` is omitted the optimizer will
5454
selects the number of times to unroll the loop.
55+
* `!dir$ prefetch designator[, designator]...`, where the designator list can be
56+
a variable or an array reference. This directive is used to insert a hint to
57+
the code generator to prefetch instructions for memory references.
5558
* `!dir$ novector` disabling vectorization on the following loop.
5659
* `!dir$ nounroll` disabling unrolling on the following loop.
5760
* `!dir$ nounroll_and_jam` disabling unrolling and jamming on the following loop.

flang/include/flang/Parser/dump-parse-tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ class ParseTreeDumper {
218218
NODE(CompilerDirective, NoVector)
219219
NODE(CompilerDirective, NoUnroll)
220220
NODE(CompilerDirective, NoUnrollAndJam)
221+
NODE(CompilerDirective, Prefetch)
221222
NODE(parser, ComplexLiteralConstant)
222223
NODE(parser, ComplexPart)
223224
NODE(parser, ComponentArraySpec)

flang/include/flang/Parser/parse-tree.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3360,6 +3360,7 @@ struct StmtFunctionStmt {
33603360
// !DIR$ NOVECTOR
33613361
// !DIR$ NOUNROLL
33623362
// !DIR$ NOUNROLL_AND_JAM
3363+
// !DIR$ PREFETCH designator[, designator]...
33633364
// !DIR$ FORCEINLINE
33643365
// !DIR$ INLINE
33653366
// !DIR$ NOINLINE
@@ -3388,6 +3389,10 @@ struct CompilerDirective {
33883389
struct UnrollAndJam {
33893390
WRAPPER_CLASS_BOILERPLATE(UnrollAndJam, std::optional<std::uint64_t>);
33903391
};
3392+
struct Prefetch {
3393+
WRAPPER_CLASS_BOILERPLATE(
3394+
Prefetch, std::list<common::Indirection<Designator>>);
3395+
};
33913396
EMPTY_CLASS(NoVector);
33923397
EMPTY_CLASS(NoUnroll);
33933398
EMPTY_CLASS(NoUnrollAndJam);
@@ -3398,7 +3403,8 @@ struct CompilerDirective {
33983403
CharBlock source;
33993404
std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>,
34003405
VectorAlways, std::list<NameValue>, Unroll, UnrollAndJam, Unrecognized,
3401-
NoVector, NoUnroll, NoUnrollAndJam, ForceInline, Inline, NoInline>
3406+
NoVector, NoUnroll, NoUnrollAndJam, ForceInline, Inline, NoInline,
3407+
Prefetch>
34023408
u;
34033409
};
34043410

flang/lib/Lower/Bridge.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3275,6 +3275,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
32753275
[&](const Fortran::parser::CompilerDirective::NoInline &) {
32763276
attachInliningDirectiveToStmt(dir, &eval);
32773277
},
3278+
[&](const Fortran::parser::CompilerDirective::Prefetch &prefetch) {
3279+
TODO(getCurrentLocation(), "!$dir prefetch");
3280+
},
32783281
[&](const auto &) {}},
32793282
dir.u);
32803283
}

flang/lib/Parser/Fortran-parsers.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,7 @@ TYPE_PARSER(construct<StatOrErrmsg>("STAT =" >> statVariable) ||
12971297
// !DIR$ LOOP COUNT (n1[, n2]...)
12981298
// !DIR$ name[=value] [, name[=value]]...
12991299
// !DIR$ UNROLL [n]
1300+
// !DIR$ PREFETCH designator[, designator]...
13001301
// !DIR$ <anything else>
13011302
constexpr auto ignore_tkr{
13021303
"IGNORE_TKR" >> optionalList(construct<CompilerDirective::IgnoreTKR>(
@@ -1311,6 +1312,8 @@ constexpr auto vectorAlways{
13111312
"VECTOR ALWAYS" >> construct<CompilerDirective::VectorAlways>()};
13121313
constexpr auto unroll{
13131314
"UNROLL" >> construct<CompilerDirective::Unroll>(maybe(digitString64))};
1315+
constexpr auto prefetch{"PREFETCH" >>
1316+
construct<CompilerDirective::Prefetch>(nonemptyList(indirect(designator)))};
13141317
constexpr auto unrollAndJam{"UNROLL_AND_JAM" >>
13151318
construct<CompilerDirective::UnrollAndJam>(maybe(digitString64))};
13161319
constexpr auto novector{"NOVECTOR" >> construct<CompilerDirective::NoVector>()};
@@ -1329,6 +1332,7 @@ TYPE_PARSER(beginDirective >> "DIR$ "_tok >>
13291332
construct<CompilerDirective>(vectorAlways) ||
13301333
construct<CompilerDirective>(unrollAndJam) ||
13311334
construct<CompilerDirective>(unroll) ||
1335+
construct<CompilerDirective>(prefetch) ||
13321336
construct<CompilerDirective>(novector) ||
13331337
construct<CompilerDirective>(nounrollAndJam) ||
13341338
construct<CompilerDirective>(nounroll) ||

flang/lib/Parser/unparse.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,6 +1855,10 @@ class UnparseVisitor {
18551855
Word("!DIR$ UNROLL");
18561856
Walk(" ", unroll.v);
18571857
},
1858+
[&](const CompilerDirective::Prefetch &prefetch) {
1859+
Word("!DIR$ PREFETCH");
1860+
Walk(" ", prefetch.v);
1861+
},
18581862
[&](const CompilerDirective::UnrollAndJam &unrollAndJam) {
18591863
Word("!DIR$ UNROLL_AND_JAM");
18601864
Walk(" ", unrollAndJam.v);

flang/lib/Semantics/resolve-names.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10065,6 +10065,7 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {
1006510065
std::holds_alternative<parser::CompilerDirective::NoUnrollAndJam>(x.u) ||
1006610066
std::holds_alternative<parser::CompilerDirective::ForceInline>(x.u) ||
1006710067
std::holds_alternative<parser::CompilerDirective::Inline>(x.u) ||
10068+
std::holds_alternative<parser::CompilerDirective::Prefetch>(x.u) ||
1006810069
std::holds_alternative<parser::CompilerDirective::NoInline>(x.u)) {
1006910070
return;
1007010071
}

flang/test/Parser/prefetch.f90

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
!RUN: %flang_fc1 -fdebug-unparse-no-sema %s 2>&1 | FileCheck %s -check-prefix=UNPARSE
2+
!RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema %s 2>&1 | FileCheck %s -check-prefix=TREE
3+
4+
subroutine test_prefetch_01(a, b)
5+
integer, intent(in) :: a
6+
integer, intent(inout) :: b(5)
7+
integer :: i = 2
8+
integer :: res
9+
10+
!TREE: | | DeclarationConstruct -> SpecificationConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'a'
11+
12+
!UNPARSE: !DIR$ PREFETCH a
13+
!dir$ prefetch a
14+
b(1) = a
15+
16+
!TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'b'
17+
18+
!UNPARSE: !DIR$ PREFETCH b
19+
!dir$ prefetch b
20+
res = sum(b)
21+
22+
!TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'a'
23+
!TREE: | | Designator -> DataRef -> ArrayElement
24+
!TREE: | | | DataRef -> Name = 'b'
25+
!TREE: | | | SectionSubscript -> SubscriptTriplet
26+
!TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '3'
27+
!TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '5'
28+
29+
!UNPARSE: !DIR$ PREFETCH a, b(3:5)
30+
!dir$ prefetch a, b(3:5)
31+
res = a + b(4)
32+
33+
!TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'res'
34+
!TREE: | | Designator -> DataRef -> ArrayElement
35+
!TREE: | | | DataRef -> Name = 'b'
36+
!TREE: | | | SectionSubscript -> Integer -> Expr -> Add
37+
!TREE: | | | | Expr -> Designator -> DataRef -> Name = 'i'
38+
!TREE: | | | | Expr -> LiteralConstant -> IntLiteralConstant = '2'
39+
40+
!UNPARSE: !DIR$ PREFETCH res, b(i+2)
41+
!dir$ prefetch res, b(i+2)
42+
res = res + b(i+2)
43+
end subroutine
44+
45+
subroutine test_prefetch_02(n, a)
46+
integer, intent(in) :: n
47+
integer, intent(in) :: a(n)
48+
type :: t
49+
real, allocatable :: x(:, :)
50+
end type t
51+
type(t) :: p
52+
53+
do i = 1, n
54+
!TREE: | | | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> ArrayElement
55+
!TREE: | | | | | DataRef -> StructureComponent
56+
!TREE: | | | | | | DataRef -> Name = 'p'
57+
!TREE: | | | | | | Name = 'x'
58+
!TREE: | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'i'
59+
!TREE: | | | | | SectionSubscript -> SubscriptTriplet
60+
!TREE: | | | | Designator -> DataRef -> Name = 'a'
61+
62+
!UNPARSE: !DIR$ PREFETCH p%x(i,:), a
63+
!dir$ prefetch p%x(i, :), a
64+
do j = 1, n
65+
!TREE: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> ArrayElement
66+
!TREE: | | | | | | | DataRef -> StructureComponent
67+
!TREE: | | | | | | | | DataRef -> Name = 'p'
68+
!TREE: | | | | | | | | Name = 'x'
69+
!TREE: | | | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'i'
70+
!TREE: | | | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'j'
71+
!TREE: | | | | | | Designator -> DataRef -> ArrayElement
72+
!TREE: | | | | | | | DataRef -> Name = 'a'
73+
!TREE: | | | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'i'
74+
75+
!UNPARSE: !DIR$ PREFETCH p%x(i,j), a(i)
76+
!dir$ prefetch p%x(i, j), a(i)
77+
p%x(i, j) = p%x(i, j) ** a(j)
78+
end do
79+
end do
80+
end subroutine

0 commit comments

Comments
 (0)