[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:29:46 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/4] [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/4] 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/4] 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);

>From 26f2e6f05147be3088bfb463f5a362e2d368233b Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Mon, 8 Apr 2024 09:29:33 -0700
Subject: [PATCH 4/4] Remove useless cast

---
 flang/lib/Semantics/check-cuda.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp
index 936de5abf3be4c..c57927b0b5bb87 100644
--- a/flang/lib/Semantics/check-cuda.cpp
+++ b/flang/lib/Semantics/check-cuda.cpp
@@ -282,7 +282,7 @@ template <bool IsCUFKernelDo> class DeviceContextChecker {
         return result;
       }
     }
-    return static_cast<const SEEK *>(nullptr);
+    return nullptr;
   }
   template <typename A> static bool IsInternalIO(const A &stmt) {
     if (stmt.iounit.has_value()) {



More information about the flang-commits mailing list