[flang-commits] [flang] cf1f871 - [Flang] Add parser support for prefetch directive (#139702)
via flang-commits
flang-commits at lists.llvm.org
Sun Nov 9 20:14:27 PST 2025
Author: Thirumalai Shaktivel
Date: 2025-11-10T09:44:22+05:30
New Revision: cf1f871023e432837581b84c8563f3b0690dd9d3
URL: https://github.com/llvm/llvm-project/commit/cf1f871023e432837581b84c8563f3b0690dd9d3
DIFF: https://github.com/llvm/llvm-project/commit/cf1f871023e432837581b84c8563f3b0690dd9d3.diff
LOG: [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.
Added:
flang/test/Parser/prefetch.f90
Modified:
flang/docs/Directives.md
flang/include/flang/Parser/dump-parse-tree.h
flang/include/flang/Parser/parse-tree.h
flang/lib/Lower/Bridge.cpp
flang/lib/Parser/Fortran-parsers.cpp
flang/lib/Parser/unparse.cpp
flang/lib/Semantics/resolve-names.cpp
Removed:
################################################################################
diff --git a/flang/docs/Directives.md b/flang/docs/Directives.md
index 2f16a8d579f8b..d157b5d397dc9 100644
--- a/flang/docs/Directives.md
+++ b/flang/docs/Directives.md
@@ -52,6 +52,9 @@ A list of non-standard directives supported by Flang
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$ 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.
* `!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.
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index b2424023b0168..1c4d2daef2a11 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -218,6 +218,7 @@ class ParseTreeDumper {
NODE(CompilerDirective, NoVector)
NODE(CompilerDirective, NoUnroll)
NODE(CompilerDirective, NoUnrollAndJam)
+ NODE(CompilerDirective, Prefetch)
NODE(parser, ComplexLiteralConstant)
NODE(parser, ComplexPart)
NODE(parser, ComponentArraySpec)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 32e444fbb2e6c..cd9429b9631d6 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3360,6 +3360,7 @@ struct StmtFunctionStmt {
// !DIR$ NOVECTOR
// !DIR$ NOUNROLL
// !DIR$ NOUNROLL_AND_JAM
+// !DIR$ PREFETCH designator[, designator]...
// !DIR$ FORCEINLINE
// !DIR$ INLINE
// !DIR$ NOINLINE
@@ -3388,6 +3389,10 @@ struct CompilerDirective {
struct UnrollAndJam {
WRAPPER_CLASS_BOILERPLATE(UnrollAndJam, std::optional<std::uint64_t>);
};
+ struct Prefetch {
+ WRAPPER_CLASS_BOILERPLATE(
+ Prefetch, std::list<common::Indirection<Designator>>);
+ };
EMPTY_CLASS(NoVector);
EMPTY_CLASS(NoUnroll);
EMPTY_CLASS(NoUnrollAndJam);
@@ -3398,7 +3403,8 @@ struct CompilerDirective {
CharBlock source;
std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>,
VectorAlways, std::list<NameValue>, Unroll, UnrollAndJam, Unrecognized,
- NoVector, NoUnroll, NoUnrollAndJam, ForceInline, Inline, NoInline>
+ NoVector, NoUnroll, NoUnrollAndJam, ForceInline, Inline, NoInline,
+ Prefetch>
u;
};
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 0f4b39a07c5da..5779bcd5d293c 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -3275,6 +3275,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
[&](const Fortran::parser::CompilerDirective::NoInline &) {
attachInliningDirectiveToStmt(dir, &eval);
},
+ [&](const Fortran::parser::CompilerDirective::Prefetch &prefetch) {
+ TODO(getCurrentLocation(), "!$dir prefetch");
+ },
[&](const auto &) {}},
dir.u);
}
diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp
index ea6a1eada2741..cdc9b0add7a48 100644
--- a/flang/lib/Parser/Fortran-parsers.cpp
+++ b/flang/lib/Parser/Fortran-parsers.cpp
@@ -1297,6 +1297,7 @@ TYPE_PARSER(construct<StatOrErrmsg>("STAT =" >> statVariable) ||
// !DIR$ LOOP COUNT (n1[, n2]...)
// !DIR$ name[=value] [, name[=value]]...
// !DIR$ UNROLL [n]
+// !DIR$ PREFETCH designator[, designator]...
// !DIR$ <anything else>
constexpr auto ignore_tkr{
"IGNORE_TKR" >> optionalList(construct<CompilerDirective::IgnoreTKR>(
@@ -1311,6 +1312,8 @@ constexpr auto vectorAlways{
"VECTOR ALWAYS" >> construct<CompilerDirective::VectorAlways>()};
constexpr auto unroll{
"UNROLL" >> construct<CompilerDirective::Unroll>(maybe(digitString64))};
+constexpr auto prefetch{"PREFETCH" >>
+ construct<CompilerDirective::Prefetch>(nonemptyList(indirect(designator)))};
constexpr auto unrollAndJam{"UNROLL_AND_JAM" >>
construct<CompilerDirective::UnrollAndJam>(maybe(digitString64))};
constexpr auto novector{"NOVECTOR" >> construct<CompilerDirective::NoVector>()};
@@ -1329,6 +1332,7 @@ TYPE_PARSER(beginDirective >> "DIR$ "_tok >>
construct<CompilerDirective>(vectorAlways) ||
construct<CompilerDirective>(unrollAndJam) ||
construct<CompilerDirective>(unroll) ||
+ construct<CompilerDirective>(prefetch) ||
construct<CompilerDirective>(novector) ||
construct<CompilerDirective>(nounrollAndJam) ||
construct<CompilerDirective>(nounroll) ||
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 6bb14a43e7b99..dc0f083c9fc95 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -1855,6 +1855,10 @@ class UnparseVisitor {
Word("!DIR$ UNROLL");
Walk(" ", unroll.v);
},
+ [&](const CompilerDirective::Prefetch &prefetch) {
+ Word("!DIR$ PREFETCH");
+ Walk(" ", prefetch.v);
+ },
[&](const CompilerDirective::UnrollAndJam &unrollAndJam) {
Word("!DIR$ UNROLL_AND_JAM");
Walk(" ", unrollAndJam.v);
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index a2062ef28d52c..09ec951a422ca 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -10065,6 +10065,7 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {
std::holds_alternative<parser::CompilerDirective::NoUnrollAndJam>(x.u) ||
std::holds_alternative<parser::CompilerDirective::ForceInline>(x.u) ||
std::holds_alternative<parser::CompilerDirective::Inline>(x.u) ||
+ std::holds_alternative<parser::CompilerDirective::Prefetch>(x.u) ||
std::holds_alternative<parser::CompilerDirective::NoInline>(x.u)) {
return;
}
diff --git a/flang/test/Parser/prefetch.f90 b/flang/test/Parser/prefetch.f90
new file mode 100644
index 0000000000000..1013a09c92117
--- /dev/null
+++ b/flang/test/Parser/prefetch.f90
@@ -0,0 +1,80 @@
+!RUN: %flang_fc1 -fdebug-unparse-no-sema %s 2>&1 | FileCheck %s -check-prefix=UNPARSE
+!RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema %s 2>&1 | FileCheck %s -check-prefix=TREE
+
+subroutine test_prefetch_01(a, b)
+ integer, intent(in) :: a
+ integer, intent(inout) :: b(5)
+ integer :: i = 2
+ integer :: res
+
+!TREE: | | DeclarationConstruct -> SpecificationConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'a'
+
+!UNPARSE: !DIR$ PREFETCH a
+ !dir$ prefetch a
+ b(1) = a
+
+!TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'b'
+
+!UNPARSE: !DIR$ PREFETCH b
+ !dir$ prefetch b
+ res = sum(b)
+
+!TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'a'
+!TREE: | | Designator -> DataRef -> ArrayElement
+!TREE: | | | DataRef -> Name = 'b'
+!TREE: | | | SectionSubscript -> SubscriptTriplet
+!TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '3'
+!TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '5'
+
+!UNPARSE: !DIR$ PREFETCH a, b(3:5)
+ !dir$ prefetch a, b(3:5)
+ res = a + b(4)
+
+!TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'res'
+!TREE: | | Designator -> DataRef -> ArrayElement
+!TREE: | | | DataRef -> Name = 'b'
+!TREE: | | | SectionSubscript -> Integer -> Expr -> Add
+!TREE: | | | | Expr -> Designator -> DataRef -> Name = 'i'
+!TREE: | | | | Expr -> LiteralConstant -> IntLiteralConstant = '2'
+
+!UNPARSE: !DIR$ PREFETCH res, b(i+2)
+ !dir$ prefetch res, b(i+2)
+ res = res + b(i+2)
+end subroutine
+
+subroutine test_prefetch_02(n, a)
+ integer, intent(in) :: n
+ integer, intent(in) :: a(n)
+ type :: t
+ real, allocatable :: x(:, :)
+ end type t
+ type(t) :: p
+
+ do i = 1, n
+!TREE: | | | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> ArrayElement
+!TREE: | | | | | DataRef -> StructureComponent
+!TREE: | | | | | | DataRef -> Name = 'p'
+!TREE: | | | | | | Name = 'x'
+!TREE: | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'i'
+!TREE: | | | | | SectionSubscript -> SubscriptTriplet
+!TREE: | | | | Designator -> DataRef -> Name = 'a'
+
+!UNPARSE: !DIR$ PREFETCH p%x(i,:), a
+ !dir$ prefetch p%x(i, :), a
+ do j = 1, n
+!TREE: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> ArrayElement
+!TREE: | | | | | | | DataRef -> StructureComponent
+!TREE: | | | | | | | | DataRef -> Name = 'p'
+!TREE: | | | | | | | | Name = 'x'
+!TREE: | | | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'i'
+!TREE: | | | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'j'
+!TREE: | | | | | | Designator -> DataRef -> ArrayElement
+!TREE: | | | | | | | DataRef -> Name = 'a'
+!TREE: | | | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'i'
+
+!UNPARSE: !DIR$ PREFETCH p%x(i,j), a(i)
+ !dir$ prefetch p%x(i, j), a(i)
+ p%x(i, j) = p%x(i, j) ** a(j)
+ end do
+ end do
+end subroutine
More information about the flang-commits
mailing list