Skip to content

[flang] Adding support of -fcoarray flang and init PRIF #151675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

JDPailleux
Copy link
Contributor

In relation to the approval and merge of the PRIF specification about multi-image features in Flang, here is a first PR to add support for the -fcoarray compilation flag and the initialization of the PRIF environment.
Other PRs will follow for adding support of lowering to PRIF.

@JDPailleux JDPailleux requested a review from ktras August 1, 2025 09:05
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' flang:driver flang Flang issues not falling into any other category flang:fir-hlfir labels Aug 1, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 1, 2025

@llvm/pr-subscribers-clang-driver
@llvm/pr-subscribers-flang-fir-hlfir

@llvm/pr-subscribers-flang-driver

Author: Jean-Didier PAILLEUX (JDPailleux)

Changes

In relation to the approval and merge of the PRIF specification about multi-image features in Flang, here is a first PR to add support for the -fcoarray compilation flag and the initialization of the PRIF environment.
Other PRs will follow for adding support of lowering to PRIF.


Full diff: https://github.com/llvm/llvm-project/pull/151675.diff

11 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+9-1)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+2)
  • (modified) flang/include/flang/Lower/LoweringOptions.def (+4)
  • (added) flang/include/flang/Optimizer/Builder/Runtime/Coarray.h (+50)
  • (modified) flang/include/flang/Optimizer/Builder/Runtime/Main.h (+1-1)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+4)
  • (modified) flang/lib/Lower/Bridge.cpp (+2-1)
  • (modified) flang/lib/Optimizer/Builder/CMakeLists.txt (+1)
  • (added) flang/lib/Optimizer/Builder/Runtime/Coarray.cpp (+35)
  • (modified) flang/lib/Optimizer/Builder/Runtime/Main.cpp (+5-2)
  • (added) flang/test/Lower/Coarray/coarray-init.f90 (+11)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index eb53821bbf4d5..a8611a8114de1 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -6962,7 +6962,6 @@ def static_libgfortran : Flag<["-"], "static-libgfortran">, Group<gfortran_Group
 // "f" options with values for gfortran.
 def fblas_matmul_limit_EQ : Joined<["-"], "fblas-matmul-limit=">, Group<gfortran_Group>;
 def fcheck_EQ : Joined<["-"], "fcheck=">, Group<gfortran_Group>;
-def fcoarray_EQ : Joined<["-"], "fcoarray=">, Group<gfortran_Group>;
 def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<gfortran_Group>;
 def ffree_line_length_VALUE : Joined<["-"], "ffree-line-length-">, Group<gfortran_Group>;
 def finit_character_EQ : Joined<["-"], "finit-character=">, Group<gfortran_Group>;
@@ -8670,6 +8669,15 @@ def fopenmp_host_ir_file_path : Separate<["-"], "fopenmp-host-ir-file-path">,
 
 } // let Visibility = [CC1Option, FC1Option]
 
+//===----------------------------------------------------------------------===//
+// Coarray Options
+//===----------------------------------------------------------------------===//
+
+def fcoarray : Flag<["-"], "fcoarray">,
+               Group<f_Group>,
+               Visibility<[FlangOption, FC1Option]>,
+               HelpText<"Enable Coarray features">;
+
 //===----------------------------------------------------------------------===//
 // SYCL Options
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 7ab41e9b85a04..d5074818de27c 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -178,6 +178,8 @@ void Flang::addCodegenOptions(const ArgList &Args,
        options::OPT_fstack_repack_arrays, options::OPT_fno_stack_repack_arrays,
        options::OPT_ftime_report, options::OPT_ftime_report_EQ,
        options::OPT_funroll_loops, options::OPT_fno_unroll_loops});
+  if (Args.hasArg(clang::driver::options::OPT_fcoarray))
+    CmdArgs.push_back("-fcoarray");
 }
 
 void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
diff --git a/flang/include/flang/Lower/LoweringOptions.def b/flang/include/flang/Lower/LoweringOptions.def
index 8135704971aa4..4b70d2df9c2f4 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -74,5 +74,9 @@ ENUM_LOWERINGOPT(SkipExternalRttiDefinition, unsigned, 1, 0)
 /// If false, lower to the complex dialect of MLIR.
 /// On by default.
 ENUM_LOWERINGOPT(ComplexDivisionToRuntime, unsigned, 1, 1)
+
+/// Enable coarrays feature.
+ENUM_LOWERINGOPT(CoarrayFeature, unsigned, 1, 0)
+
 #undef LOWERINGOPT
 #undef ENUM_LOWERINGOPT
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Coarray.h b/flang/include/flang/Optimizer/Builder/Runtime/Coarray.h
new file mode 100644
index 0000000000000..83561fffc3ff0
--- /dev/null
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Coarray.h
@@ -0,0 +1,50 @@
+//===-- Coarray.h -- generate Coarray intrinsics runtime calls --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COARRAY_H
+#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COARRAY_H
+
+#include "flang/Lower/AbstractConverter.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+
+namespace fir {
+class ExtendedValue;
+class FirOpBuilder;
+} // namespace fir
+
+namespace fir::runtime {
+
+// Get the function type for a prif subroutine with a variable number of
+// arguments
+#define PRIF_FUNCTYPE(...)                                                     \
+  mlir::FunctionType::get(builder.getContext(), /*inputs*/ {__VA_ARGS__},      \
+                          /*result*/ {})
+
+// Default prefix for type of PRIF compiled with LLVM
+#define PRIFTYPE_PREFIX "_QM__prifT"
+#define PRIFTYPE(fmt)                                                          \
+  []() {                                                                       \
+    std::ostringstream oss;                                                    \
+    oss << PRIFTYPE_PREFIX << fmt;                                             \
+    return oss.str();                                                          \
+  }()
+
+// Default prefix for subroutines of PRIF compiled with LLVM
+#define PRIFSUB_PREFIX "_QMprifPprif_"
+#define PRIFNAME_SUB(fmt)                                                      \
+  []() {                                                                       \
+    std::ostringstream oss;                                                    \
+    oss << PRIFSUB_PREFIX << fmt;                                              \
+    return oss.str();                                                          \
+  }()
+
+/// Generate Call to runtime prif_init
+mlir::Value genInitCoarray(fir::FirOpBuilder &builder, mlir::Location loc);
+
+} // namespace fir::runtime
+#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COARRAY_H
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Main.h b/flang/include/flang/Optimizer/Builder/Runtime/Main.h
index a0586deade42a..d4067b367f73e 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Main.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Main.h
@@ -25,7 +25,7 @@ namespace fir::runtime {
 
 void genMain(fir::FirOpBuilder &builder, mlir::Location loc,
              const std::vector<Fortran::lower::EnvironmentDefault> &defs,
-             bool initCuda = false);
+             bool initCuda = false, bool initCoarrayEnv = false);
 }
 
 #endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_MAIN_H
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 111c5aa48726f..88065a5b4fb2f 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1152,6 +1152,10 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
       diags.Report(diagID);
     }
   }
+  // -fcoarray
+  if (args.hasArg(clang::driver::options::OPT_fcoarray))
+    res.getLoweringOpts().setCoarrayFeature(1);
+
   return diags.getNumErrors() == numErrorsBefore;
 }
 
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index ac3669c907fbc..9d6eed1d4822d 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -475,7 +475,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         fir::runtime::genMain(*builder, toLocation(),
                               bridge.getEnvironmentDefaults(),
                               getFoldingContext().languageFeatures().IsEnabled(
-                                  Fortran::common::LanguageFeature::CUDA));
+                                  Fortran::common::LanguageFeature::CUDA),
+                              getLoweringOptions().getCoarrayFeature());
       });
 
     finalizeOpenMPLowering(globalOmpRequiresSymbol);
diff --git a/flang/lib/Optimizer/Builder/CMakeLists.txt b/flang/lib/Optimizer/Builder/CMakeLists.txt
index 31ae395805faf..8fb36a750d433 100644
--- a/flang/lib/Optimizer/Builder/CMakeLists.txt
+++ b/flang/lib/Optimizer/Builder/CMakeLists.txt
@@ -16,6 +16,7 @@ add_flang_library(FIRBuilder
   Runtime/Allocatable.cpp
   Runtime/ArrayConstructor.cpp
   Runtime/Assign.cpp
+  Runtime/Coarray.cpp
   Runtime/Character.cpp
   Runtime/Command.cpp
   Runtime/CUDA/Descriptor.cpp
diff --git a/flang/lib/Optimizer/Builder/Runtime/Coarray.cpp b/flang/lib/Optimizer/Builder/Runtime/Coarray.cpp
new file mode 100644
index 0000000000000..bcc4d63e22f26
--- /dev/null
+++ b/flang/lib/Optimizer/Builder/Runtime/Coarray.cpp
@@ -0,0 +1,35 @@
+//===-- Coarray.cpp -- runtime API for coarray intrinsics -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Builder/Runtime/Coarray.h"
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
+#include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "flang/Optimizer/Support/InternalNames.h"
+#include "flang/Semantics/scope.h"
+#include "flang/Semantics/tools.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "llvm/ADT/TypeSwitch.h"
+
+using namespace Fortran::runtime;
+using namespace Fortran::semantics;
+
+/// Generate Call to runtime prif_init
+mlir::Value fir::runtime::genInitCoarray(fir::FirOpBuilder &builder,
+                                         mlir::Location loc) {
+  mlir::Type i32Ty = builder.getI32Type();
+  mlir::Value result = builder.createTemporary(loc, i32Ty);
+  mlir::FunctionType ftype = PRIF_FUNCTYPE(builder.getRefType(i32Ty));
+  mlir::func::FuncOp funcOp =
+      builder.createFunction(loc, PRIFNAME_SUB("init"), ftype);
+  llvm::SmallVector<mlir::Value> args =
+      fir::runtime::createArguments(builder, loc, ftype, result);
+  builder.create<fir::CallOp>(loc, funcOp, args);
+  return builder.create<fir::LoadOp>(loc, result);
+}
diff --git a/flang/lib/Optimizer/Builder/Runtime/Main.cpp b/flang/lib/Optimizer/Builder/Runtime/Main.cpp
index d35f687167b05..d303e0ad63842 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Main.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Main.cpp
@@ -10,6 +10,7 @@
 #include "flang/Lower/EnvironmentDefault.h"
 #include "flang/Optimizer/Builder/BoxValue.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/Runtime/Coarray.h"
 #include "flang/Optimizer/Builder/Runtime/EnvironmentDefaults.h"
 #include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
 #include "flang/Optimizer/Dialect/FIROps.h"
@@ -23,8 +24,8 @@ using namespace Fortran::runtime;
 /// Create a `int main(...)` that calls the Fortran entry point
 void fir::runtime::genMain(
     fir::FirOpBuilder &builder, mlir::Location loc,
-    const std::vector<Fortran::lower::EnvironmentDefault> &defs,
-    bool initCuda) {
+    const std::vector<Fortran::lower::EnvironmentDefault> &defs, bool initCuda,
+    bool initCoarrayEnv) {
   auto *context = builder.getContext();
   auto argcTy = builder.getDefaultIntegerType();
   auto ptrTy = mlir::LLVM::LLVMPointerType::get(context);
@@ -69,6 +70,8 @@ void fir::runtime::genMain(
         loc, RTNAME_STRING(CUFInit), mlir::FunctionType::get(context, {}, {}));
     fir::CallOp::create(builder, loc, initFn);
   }
+  if (initCoarrayEnv)
+    fir::runtime::genInitCoarray(builder, loc);
 
   fir::CallOp::create(builder, loc, qqMainFn);
   fir::CallOp::create(builder, loc, stopFn);
diff --git a/flang/test/Lower/Coarray/coarray-init.f90 b/flang/test/Lower/Coarray/coarray-init.f90
new file mode 100644
index 0000000000000..055bc0fc4da72
--- /dev/null
+++ b/flang/test/Lower/Coarray/coarray-init.f90
@@ -0,0 +1,11 @@
+! RUN: %flang_fc1 -emit-hlfir -fcoarray %s -o - | FileCheck %s --check-prefixes=ALL,COARRAY
+! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s --check-prefixes=ALL,NOCOARRAY
+
+program test_init
+
+end 
+
+! ALL-LABEL: func.func @main
+! ALL: fir.call @_FortranAProgramStart
+! COARRAY: fir.call @_QMprifPprif_init(%[[ARG:.*]]) fastmath<contract> : (!fir.ref<i32>) -> ()
+! NOCOARRAY-NOT: fir.call @_QMprifPprif_init(%[[ARG:.*]]) fastmath<contract> : (!fir.ref<i32>) -> ()

@JDPailleux JDPailleux requested review from ergawy and jeanPerier August 6, 2025 15:07
@ktras
Copy link
Contributor

ktras commented Aug 7, 2025

@JDPailleux Could you please rebase and resolve the merge conflicts that exist currently? It is a trivial conflict in file flang/include/flang/Lower/LoweringOptions.def. I will be doing a review later today and I will be checking to make sure that this can be linked against a PRIF runtime library and produces an executable that can run with multiple images.

@@ -74,5 +74,9 @@ ENUM_LOWERINGOPT(SkipExternalRttiDefinition, unsigned, 1, 0)
/// If false, lower to the complex dialect of MLIR.
/// On by default.
ENUM_LOWERINGOPT(ComplexDivisionToRuntime, unsigned, 1, 1)

/// Enable coarrays feature.
ENUM_LOWERINGOPT(CoarrayFeature, unsigned, 1, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to use LanguageFeatures enum like it is done for OpenMP, OpenACC and CUDA Fortran.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it would be better to put this as a lowering option, as it will activate lowering to PRIF. But I will apply the suggested change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is your plan to have multiple lowering for coarrays? If so, it is fine for me but the option should be renamed so it is specific to PRIF.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that's not planned. I'll make the change.

Comment on lines 28 to 43
// Default prefix for type of PRIF compiled with LLVM
#define PRIFTYPE_PREFIX "_QM__prifT"
#define PRIFTYPE(fmt) \
[]() { \
std::ostringstream oss; \
oss << PRIFTYPE_PREFIX << fmt; \
return oss.str(); \
}()

// Default prefix for subroutines of PRIF compiled with LLVM
#define PRIFSUB_PREFIX "_QMprifPprif_"
#define PRIFNAME_SUB(fmt) \
[]() { \
std::ostringstream oss; \
oss << PRIFSUB_PREFIX << fmt; \
return oss.str(); \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use functions in flang/lib/Optimizer/Support/InternalNames.cpp so the mangled name is kept up to date in case of changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes of course

Copy link
Contributor

@ktras ktras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JDPailleux Thanks, this is a great start. I can confirm that by using this branch, I am able to build a Flang that can build a PRIF runtime library (Caffeine) and then link to that library while compiling an executable that can then be run with multiple images.

This is not a strong requirement from me, but what do you think about adding a warning when users use the -fcoarray flag, so that it is clear that the features associated with this flag are still in development. Perhaps something similar to the warning when users provide the -fdo-concurrent-to-openmp flag? That warning is "Mapping do concurrent to OpenMP is still experimental." and it is produced in flang/lib/Frontend/FrontendActions.cpp. If a similar warning is deemed helpful for users of the -fcoarray flag, I would recommend something like: "Support for multi image Fortran features is still experimental and in development." Since any specific multi image features that are not yet lowered would be caught by the general error for features that are not yet implemented, this additional warning with the -fcoarray flag may not be necessary, it is just a potential option.

Please also note and respond to the review feedback above from @clementval.

@JDPailleux
Copy link
Contributor Author

@JDPailleux Thanks, this is a great start. I can confirm that by using this branch, I am able to build a Flang that can build a PRIF runtime library (Caffeine) and then link to that library while compiling an executable that can then be run with multiple images.

This is not a strong requirement from me, but what do you think about adding a warning when users use the -fcoarray flag, so that it is clear that the features associated with this flag are still in development. Perhaps something similar to the warning when users provide the -fdo-concurrent-to-openmp flag? That warning is "Mapping do concurrent to OpenMP is still experimental." and it is produced in flang/lib/Frontend/FrontendActions.cpp. If a similar warning is deemed helpful for users of the -fcoarray flag, I would recommend something like: "Support for multi image Fortran features is still experimental and in development." Since any specific multi image features that are not yet lowered would be caught by the general error for features that are not yet implemented, this additional warning with the -fcoarray flag may not be necessary, it is just a potential option.

Please also note and respond to the review feedback above from @clementval.

Thank you for your reply. I do think it would be useful to include a warning to indicate that it is still experimental. So I'll do that

@JDPailleux JDPailleux force-pushed the jdp/flang/coarray_flag_prif_init branch from 18eeadc to b61099c Compare August 12, 2025 18:01
@JDPailleux JDPailleux requested a review from ktras August 12, 2025 18:03
@ktras ktras requested a review from clementval August 12, 2025 19:10
@JDPailleux JDPailleux force-pushed the jdp/flang/coarray_flag_prif_init branch from 19117ca to 5117458 Compare August 13, 2025 06:55
@JDPailleux JDPailleux requested a review from clementval August 13, 2025 07:55
Copy link
Contributor

@clementval clementval left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@JDPailleux JDPailleux force-pushed the jdp/flang/coarray_flag_prif_init branch from 5117458 to 9ade3f4 Compare August 14, 2025 06:33
@JDPailleux
Copy link
Contributor Author

Thanks for the review !

Copy link
Contributor

@ktras ktras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @JDPailleux for addressing all the review comments from myself and @clementval. After your latest changes, I reconfirmed that I am able to build Flang and the PRIF runtime library (Caffeine) and then link to that library when using Flang to compile an executable that can then be run with multiple images.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category flang:driver flang:fir-hlfir flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants