[flang-commits] [flang] [flang][DRAFT] Copy-in/Copy-out determination (PR #151408)

Eugene Epshteyn via flang-commits flang-commits at lists.llvm.org
Thu Aug 7 09:09:22 PDT 2025


https://github.com/eugeneepshteyn updated https://github.com/llvm/llvm-project/pull/151408

>From 54c0158dcce9b5ebb6a3658298dedcda72b41f52 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 30 Jul 2025 17:08:06 -0400
Subject: [PATCH 1/4] [flang][DRAFT] Copy-in/Copy-out determination

Plumbing/API for copy-in/copy-out
---
 flang/include/flang/Evaluate/call.h | 19 +++++++++++++++++--
 flang/lib/Evaluate/call.cpp         | 16 ++++++++++++++++
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/flang/include/flang/Evaluate/call.h b/flang/include/flang/Evaluate/call.h
index 2a5929b873d74..ac11527e4ecaa 100644
--- a/flang/include/flang/Evaluate/call.h
+++ b/flang/include/flang/Evaluate/call.h
@@ -52,7 +52,7 @@ using SymbolRef = common::Reference<const Symbol>;
 
 class ActualArgument {
 public:
-  ENUM_CLASS(Attr, PassedObject, PercentVal, PercentRef);
+  ENUM_CLASS(Attr, PassedObject, PercentVal, PercentRef, CopyIn, CopyOut);
   using Attrs = common::EnumSet<Attr, Attr_enumSize>;
 
   // Dummy arguments that are TYPE(*) can be forwarded as actual arguments.
@@ -131,7 +131,6 @@ class ActualArgument {
     return *this;
   }
 
-  bool Matches(const characteristics::DummyArgument &) const;
   common::Intent dummyIntent() const { return dummyIntent_; }
   ActualArgument &set_dummyIntent(common::Intent intent) {
     dummyIntent_ = intent;
@@ -161,6 +160,20 @@ class ActualArgument {
     return *this;
   }
 
+  // This actual argument may need copy-in before the procedure call
+  bool mayNeedCopyIn() const { return attrs_.test(Attr::CopyIn); };
+  ActualArgument &set_mayNeedCopyIn() {
+    attrs_ = attrs_ + Attr::CopyIn;
+    return *this;
+  }
+
+  // This actual argument may need copy-out after the procedure call
+  bool mayNeedCopyOut() const { return attrs_.test(Attr::CopyOut); };
+  ActualArgument &set_mayNeedCopyOut() {
+    attrs_ = attrs_ + Attr::CopyOut;
+    return *this;
+  }
+
 private:
   // Subtlety: There is a distinction that must be maintained here between an
   // actual argument expression that is a variable and one that is not,
@@ -272,6 +285,8 @@ class ProcedureRef {
   bool operator==(const ProcedureRef &) const;
   llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
 
+  void DetermineCopyInOut();
+
 protected:
   ProcedureDesignator proc_;
   ActualArguments arguments_;
diff --git a/flang/lib/Evaluate/call.cpp b/flang/lib/Evaluate/call.cpp
index f77df92a7597a..1e582a516a694 100644
--- a/flang/lib/Evaluate/call.cpp
+++ b/flang/lib/Evaluate/call.cpp
@@ -13,6 +13,7 @@
 #include "flang/Evaluate/expression.h"
 #include "flang/Evaluate/tools.h"
 #include "flang/Semantics/symbol.h"
+#include "flang/Semantics/semantics.h"
 #include "flang/Support/Fortran.h"
 
 namespace Fortran::evaluate {
@@ -247,4 +248,19 @@ ProcedureRef::~ProcedureRef() {}
 
 void ProcedureRef::Deleter(ProcedureRef *p) { delete p; }
 
+void ProcedureRef::DetermineCopyInOut() {
+  if (!proc().GetSymbol()) {
+    return;
+  }
+  // Get folding context of the call site owner
+  FoldingContext &fc{proc_.GetSymbol()->owner().context().foldingContext()};
+  auto procInfo{characteristics::Procedure::Characterize(
+      proc(), fc, /*emitError=*/false)};
+  if (!procInfo) {
+    return;
+  }
+  // TODO: at this point have dummy arguments as procInfo->dummyArguments
+  // and have actual arguments via arguments_
+}
+
 } // namespace Fortran::evaluate

>From 808fb20c3e4d6dc80b7e3793fb28b4f7854b07f8 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 30 Jul 2025 17:44:37 -0400
Subject: [PATCH 2/4] Call DetermineCopyInOut() from lowering

---
 flang/include/flang/Lower/CallInterface.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/flang/include/flang/Lower/CallInterface.h b/flang/include/flang/Lower/CallInterface.h
index 72bc9dd890a94..eca697d474c47 100644
--- a/flang/include/flang/Lower/CallInterface.h
+++ b/flang/include/flang/Lower/CallInterface.h
@@ -284,6 +284,9 @@ class CallerInterface : public CallInterface<CallerInterface> {
   CallerInterface(const Fortran::evaluate::ProcedureRef &p,
                   Fortran::lower::AbstractConverter &c)
       : CallInterface{c}, procRef{p} {
+    // Ensure that procRef gathers necessary information to determine the
+    // need for copy-in and copy-out
+    const_cast<Fortran::evaluate::ProcedureRef &>(procRef).DetermineCopyInOut();
     declare();
     mapPassedEntities();
     actualInputs.resize(getNumFIRArguments());

>From 28bc5bd95f83f131c4a905f69e402fc97a1b7e9d Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 30 Jul 2025 18:20:23 -0400
Subject: [PATCH 3/4] clang-format

---
 flang/lib/Evaluate/call.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/lib/Evaluate/call.cpp b/flang/lib/Evaluate/call.cpp
index 1e582a516a694..0cfad4cfae17e 100644
--- a/flang/lib/Evaluate/call.cpp
+++ b/flang/lib/Evaluate/call.cpp
@@ -12,8 +12,8 @@
 #include "flang/Evaluate/check-expression.h"
 #include "flang/Evaluate/expression.h"
 #include "flang/Evaluate/tools.h"
-#include "flang/Semantics/symbol.h"
 #include "flang/Semantics/semantics.h"
+#include "flang/Semantics/symbol.h"
 #include "flang/Support/Fortran.h"
 
 namespace Fortran::evaluate {

>From f44b9459f6e2c0f60d6f66d00ec37d383befe021 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 30 Jul 2025 19:54:01 -0400
Subject: [PATCH 4/4] DetermineCopyInOut() is now called from ProcedureRef
 constructor

---
 flang/include/flang/Evaluate/call.h       | 8 ++++++--
 flang/include/flang/Lower/CallInterface.h | 3 ---
 flang/lib/Evaluate/call.cpp               | 2 +-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/flang/include/flang/Evaluate/call.h b/flang/include/flang/Evaluate/call.h
index ac11527e4ecaa..56338901b22bb 100644
--- a/flang/include/flang/Evaluate/call.h
+++ b/flang/include/flang/Evaluate/call.h
@@ -248,7 +248,11 @@ class ProcedureRef {
   ProcedureRef(ProcedureDesignator &&p, ActualArguments &&a,
       bool hasAlternateReturns = false)
       : proc_{std::move(p)}, arguments_{std::move(a)},
-        hasAlternateReturns_{hasAlternateReturns} {}
+        hasAlternateReturns_{hasAlternateReturns} {
+    // Gathers necessary information to determine the need for copy-in and
+    // copy-out
+    DetermineCopyInOut();
+  }
   ~ProcedureRef();
   static void Deleter(ProcedureRef *);
 
@@ -285,9 +289,9 @@ class ProcedureRef {
   bool operator==(const ProcedureRef &) const;
   llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
 
+protected:
   void DetermineCopyInOut();
 
-protected:
   ProcedureDesignator proc_;
   ActualArguments arguments_;
   Chevrons chevrons_;
diff --git a/flang/include/flang/Lower/CallInterface.h b/flang/include/flang/Lower/CallInterface.h
index eca697d474c47..72bc9dd890a94 100644
--- a/flang/include/flang/Lower/CallInterface.h
+++ b/flang/include/flang/Lower/CallInterface.h
@@ -284,9 +284,6 @@ class CallerInterface : public CallInterface<CallerInterface> {
   CallerInterface(const Fortran::evaluate::ProcedureRef &p,
                   Fortran::lower::AbstractConverter &c)
       : CallInterface{c}, procRef{p} {
-    // Ensure that procRef gathers necessary information to determine the
-    // need for copy-in and copy-out
-    const_cast<Fortran::evaluate::ProcedureRef &>(procRef).DetermineCopyInOut();
     declare();
     mapPassedEntities();
     actualInputs.resize(getNumFIRArguments());
diff --git a/flang/lib/Evaluate/call.cpp b/flang/lib/Evaluate/call.cpp
index 0cfad4cfae17e..c558335c16545 100644
--- a/flang/lib/Evaluate/call.cpp
+++ b/flang/lib/Evaluate/call.cpp
@@ -255,7 +255,7 @@ void ProcedureRef::DetermineCopyInOut() {
   // Get folding context of the call site owner
   FoldingContext &fc{proc_.GetSymbol()->owner().context().foldingContext()};
   auto procInfo{characteristics::Procedure::Characterize(
-      proc(), fc, /*emitError=*/false)};
+      proc_, fc, /*emitError=*/true)};
   if (!procInfo) {
     return;
   }



More information about the flang-commits mailing list