[flang-commits] [flang] [flang][cuda] Allow list-directed PRINT and WRITE stmt in device code (PR #87415)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Mon Apr 8 09:23:21 PDT 2024
https://github.com/clementval updated https://github.com/llvm/llvm-project/pull/87415
>From f3a7a96d3c2af5fa7d153f20c06bcd945bbca52c Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Tue, 2 Apr 2024 11:04:57 -0700
Subject: [PATCH 1/3] [flang][cuda] Allow list-directed PRINT and WRITE stmt in
device code
The specification allow list-directed PRINT and WRITE statements to
appear in device code. This patch relax the semantic check to allow them.
3.6.11.
List-directed PRINT and WRITE statements to the default unit may be used when
compiling for compute capability 2.0 and higher; all other uses of PRINT and
WRITE are disallowed.
---
flang/lib/Semantics/check-cuda.cpp | 16 ++++++++++++++++
flang/test/Semantics/cuf09.cuf | 10 ++++++++++
2 files changed, 26 insertions(+)
diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp
index c0c6ff4c1a2ba3..fc04c37136c715 100644
--- a/flang/lib/Semantics/check-cuda.cpp
+++ b/flang/lib/Semantics/check-cuda.cpp
@@ -278,6 +278,22 @@ template <bool IsCUFKernelDo> class DeviceContextChecker {
void Check(const parser::ActionStmt &stmt, const parser::CharBlock &source) {
common::visit(
common::visitors{
+ [&](const common::Indirection<parser::PrintStmt> &x) {
+ if (!std::holds_alternative<Fortran::parser::Star>(
+ std::get<Fortran::parser::Format>(x.value().t).u)) {
+ context_.Say(source,
+ "Only list-directed PRINT statement may appear in device code"_err_en_US);
+ }
+ },
+ [&](const common::Indirection<parser::WriteStmt> &x) {
+ if (x.value().format) {
+ if (!std::holds_alternative<Fortran::parser::Star>(
+ x.value().format->u)) {
+ context_.Say(source,
+ "Only list-directed WRITE statement may appear in device code"_err_en_US);
+ }
+ }
+ },
[&](const auto &x) {
if (auto msg{ActionStmtChecker<IsCUFKernelDo>::WhyNotOk(x)}) {
context_.Say(source, std::move(*msg));
diff --git a/flang/test/Semantics/cuf09.cuf b/flang/test/Semantics/cuf09.cuf
index 4bc93132044fdd..61ce10aa7f10c3 100644
--- a/flang/test/Semantics/cuf09.cuf
+++ b/flang/test/Semantics/cuf09.cuf
@@ -7,6 +7,16 @@ module m
do k=1,10
end do
end
+ attributes(device) subroutine devsub2
+ real, device :: x(10)
+ print*,'from device'
+ !ERROR: Only list-directed PRINT statement may appear in device code
+ print '(f10.5)', (x(ivar), ivar = 1, 10)
+
+ write(*,*), "Hello world from device!"
+ !ERROR: Only list-directed WRITE statement may appear in device code
+ write(*,'(10F4.1)'), x
+ end
end
program main
>From 628e0382c3d5457bc614c9410dd3e526c1c028b2 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Wed, 3 Apr 2024 14:41:28 -0700
Subject: [PATCH 2/3] Relax the restriction and warn
---
flang/lib/Semantics/check-cuda.cpp | 71 +++++++++++++++++++++++++-----
flang/test/Semantics/cuf09.cuf | 6 +--
2 files changed, 62 insertions(+), 15 deletions(-)
diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp
index fc04c37136c715..cb8ec7be4c05ef 100644
--- a/flang/lib/Semantics/check-cuda.cpp
+++ b/flang/lib/Semantics/check-cuda.cpp
@@ -275,24 +275,73 @@ template <bool IsCUFKernelDo> class DeviceContextChecker {
},
ec.u);
}
+ template <typename SEEK, typename A>
+ static const auto *GetIOControl(const A &stmt) {
+ for (const auto &spec : stmt.controls) {
+ if (const auto *result = std::get_if<SEEK>(&spec.u)) {
+ return result;
+ }
+ }
+ return static_cast<const SEEK *>(nullptr);
+ }
+ template <typename A> static bool IsInternalIO(const A &stmt) {
+ if (stmt.iounit.has_value()) {
+ return std::holds_alternative<Fortran::parser::Variable>(stmt.iounit->u);
+ }
+ if (auto *unit = GetIOControl<Fortran::parser::IoUnit>(stmt)) {
+ return std::holds_alternative<Fortran::parser::Variable>(unit->u);
+ }
+ return false;
+ }
+ void WarnOnIoStmt(const parser::CharBlock &source) {
+ context_.Say(
+ source, "I/O statement might not be supported on device"_warn_en_US);
+ }
+ template <typename A>
+ void WarnIfNotInternal(const A &stmt, const parser::CharBlock &source) {
+ if (!IsInternalIO(stmt)) {
+ WarnOnIoStmt(source);
+ }
+ }
void Check(const parser::ActionStmt &stmt, const parser::CharBlock &source) {
common::visit(
common::visitors{
- [&](const common::Indirection<parser::PrintStmt> &x) {
- if (!std::holds_alternative<Fortran::parser::Star>(
- std::get<Fortran::parser::Format>(x.value().t).u)) {
- context_.Say(source,
- "Only list-directed PRINT statement may appear in device code"_err_en_US);
- }
- },
+ [&](const common::Indirection<parser::PrintStmt> &) {},
[&](const common::Indirection<parser::WriteStmt> &x) {
- if (x.value().format) {
- if (!std::holds_alternative<Fortran::parser::Star>(
+ if (x.value().format) { // Formatted write to '*' or '6'
+ if (std::holds_alternative<Fortran::parser::Star>(
x.value().format->u)) {
- context_.Say(source,
- "Only list-directed WRITE statement may appear in device code"_err_en_US);
+ if (x.value().iounit) {
+ if (std::holds_alternative<Fortran::parser::Star>(
+ x.value().iounit->u)) {
+ return;
+ }
+ }
+ return;
}
}
+ WarnIfNotInternal(x.value(), source);
+ },
+ [&](const common::Indirection<parser::CloseStmt> &x) {
+ WarnOnIoStmt(source);
+ },
+ [&](const common::Indirection<parser::EndfileStmt> &x) {
+ WarnOnIoStmt(source);
+ },
+ [&](const common::Indirection<parser::OpenStmt> &x) {
+ WarnOnIoStmt(source);
+ },
+ [&](const common::Indirection<parser::ReadStmt> &x) {
+ WarnIfNotInternal(x.value(), source);
+ },
+ [&](const common::Indirection<parser::InquireStmt> &x) {
+ WarnOnIoStmt(source);
+ },
+ [&](const common::Indirection<parser::RewindStmt> &x) {
+ WarnOnIoStmt(source);
+ },
+ [&](const common::Indirection<parser::BackspaceStmt> &x) {
+ WarnOnIoStmt(source);
},
[&](const auto &x) {
if (auto msg{ActionStmtChecker<IsCUFKernelDo>::WhyNotOk(x)}) {
diff --git a/flang/test/Semantics/cuf09.cuf b/flang/test/Semantics/cuf09.cuf
index 61ce10aa7f10c3..d2d4d239815e4b 100644
--- a/flang/test/Semantics/cuf09.cuf
+++ b/flang/test/Semantics/cuf09.cuf
@@ -10,12 +10,10 @@ module m
attributes(device) subroutine devsub2
real, device :: x(10)
print*,'from device'
- !ERROR: Only list-directed PRINT statement may appear in device code
print '(f10.5)', (x(ivar), ivar = 1, 10)
-
write(*,*), "Hello world from device!"
- !ERROR: Only list-directed WRITE statement may appear in device code
- write(*,'(10F4.1)'), x
+ !WARNING: I/O statement might not be supported on device
+ write(12,'(10F4.1)'), x
end
end
>From 1f020cb4358dc19db4f8419d753f0c9d3bb1794b Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Mon, 8 Apr 2024 09:23:09 -0700
Subject: [PATCH 3/3] Brace init + remove extra return
---
flang/lib/Semantics/check-cuda.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp
index cb8ec7be4c05ef..936de5abf3be4c 100644
--- a/flang/lib/Semantics/check-cuda.cpp
+++ b/flang/lib/Semantics/check-cuda.cpp
@@ -276,9 +276,9 @@ template <bool IsCUFKernelDo> class DeviceContextChecker {
ec.u);
}
template <typename SEEK, typename A>
- static const auto *GetIOControl(const A &stmt) {
+ static const SEEK *GetIOControl(const A &stmt) {
for (const auto &spec : stmt.controls) {
- if (const auto *result = std::get_if<SEEK>(&spec.u)) {
+ if (const auto *result{std::get_if<SEEK>(&spec.u)}) {
return result;
}
}
@@ -288,7 +288,7 @@ template <bool IsCUFKernelDo> class DeviceContextChecker {
if (stmt.iounit.has_value()) {
return std::holds_alternative<Fortran::parser::Variable>(stmt.iounit->u);
}
- if (auto *unit = GetIOControl<Fortran::parser::IoUnit>(stmt)) {
+ if (auto *unit{GetIOControl<Fortran::parser::IoUnit>(stmt)}) {
return std::holds_alternative<Fortran::parser::Variable>(unit->u);
}
return false;
@@ -317,7 +317,6 @@ template <bool IsCUFKernelDo> class DeviceContextChecker {
return;
}
}
- return;
}
}
WarnIfNotInternal(x.value(), source);
More information about the flang-commits
mailing list