[flang-commits] [flang] 2e63436 - [Flang][OpenMP][Driver][MLIR] Port fopenmp-host-ir-file-path flag and add MLIR module attribute to proliferate to OpenMP IR lowering
Andrew Gozillon via flang-commits
flang-commits at lists.llvm.org
Mon Apr 24 08:06:40 PDT 2023
Author: Andrew Gozillon
Date: 2023-04-24T10:06:21-05:00
New Revision: 2e634367be6a2ed6b8a4ee5c29b720dd90c0d70a
URL: https://github.com/llvm/llvm-project/commit/2e634367be6a2ed6b8a4ee5c29b720dd90c0d70a
DIFF: https://github.com/llvm/llvm-project/commit/2e634367be6a2ed6b8a4ee5c29b720dd90c0d70a.diff
LOG: [Flang][OpenMP][Driver][MLIR] Port fopenmp-host-ir-file-path flag and add MLIR module attribute to proliferate to OpenMP IR lowering
This patch ports the fopenmp-host-ir-file-path flag from Clang to Flang-new, this flag
is added by the driver to the device pass when doing two phase compilation (device + host).
This flag is then applied to the module when compiling during the OpenMP device phase.
This file can then be utilised during lowering of the OpenMP dialect to LLVM-IR, which
allows the device and host to maintain 1:1 mapping of OpenMP metadata for variables
during lowering via the OpenMPIRBuilders loadOffloadInfoMetadata facilities
(which is used for declare target and I believe target regions as well).
Reviewer: awarzynski
Differential Revision: https://reviews.llvm.org/D148038
Added:
flang/test/Lower/OpenMP/omp-host-ir-flag.f90
Modified:
clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/Flang.cpp
flang/include/flang/Frontend/LangOptions.h
flang/include/flang/Tools/CrossToolHelpers.h
flang/lib/Frontend/CompilerInvocation.cpp
flang/test/Driver/driver-help.f90
flang/test/Driver/omp-driver-offload.f90
mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 3b07244b98e82..d8ae398c61218 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -6554,12 +6554,14 @@ def fno_cuda_host_device_constexpr : Flag<["-"], "fno-cuda-host-device-constexpr
// OpenMP Options
//===----------------------------------------------------------------------===//
+let Flags = [CC1Option, FC1Option, NoDriverOption] in {
+
def fopenmp_is_device : Flag<["-"], "fopenmp-is-device">,
- HelpText<"Generate code only for an OpenMP target device.">,
- Flags<[CC1Option, FC1Option, NoDriverOption]>;
+ HelpText<"Generate code only for an OpenMP target device.">;
def fopenmp_host_ir_file_path : Separate<["-"], "fopenmp-host-ir-file-path">,
- HelpText<"Path to the IR file produced by the frontend for the host.">,
- Flags<[CC1Option, NoDriverOption]>;
+ HelpText<"Path to the IR file produced by the frontend for the host.">;
+
+} // let Flags = [CC1Option, FC1Option, NoDriverOption]
//===----------------------------------------------------------------------===//
// SYCL Options
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 300072db35edc..ffd30af08fd0d 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -194,15 +194,29 @@ void Flang::addOffloadOptions(Compilation &C, const InputInfoList &Inputs,
// Skips the primary input file, which is the input file that the compilation
// proccess will be executed upon (e.g. the host bitcode file) and
- // adds the other secondary input (e.g. device bitcode files for embedding)
- // to the embed offload object. This is condensed logic from the Clang driver
- // for embedding offload objects during HostOffloading.
- if (IsHostOffloadingAction) {
- for (size_t i = 1; i < Inputs.size(); ++i) {
- if (Inputs[i].getType() != types::TY_Nothing)
- CmdArgs.push_back(
- Args.MakeArgString("-fembed-offload-object=" +
- getToolChain().getInputFilename(Inputs[i])));
+ // adds other secondary input (e.g. device bitcode files for embedding to the
+ // -fembed-offload-object argument or the host IR file for proccessing
+ // during device compilation to the fopenmp-host-ir-file-path argument via
+ // OpenMPDeviceInput). This is condensed logic from the ConstructJob
+ // function inside of the Clang driver for pushing on further input arguments
+ // needed for offloading during various phases of compilation.
+ for (size_t i = 1; i < Inputs.size(); ++i) {
+ if (Inputs[i].getType() == types::TY_Nothing) {
+ // contains nothing, so it's skippable
+ } else if (IsHostOffloadingAction) {
+ CmdArgs.push_back(
+ Args.MakeArgString("-fembed-offload-object=" +
+ getToolChain().getInputFilename(Inputs[i])));
+ } else if (IsOpenMPDevice) {
+ if (Inputs[i].getFilename()) {
+ CmdArgs.push_back("-fopenmp-host-ir-file-path");
+ CmdArgs.push_back(Args.MakeArgString(Inputs[i].getFilename()));
+ } else {
+ llvm_unreachable("missing openmp host-ir file for device offloading");
+ }
+ } else {
+ llvm_unreachable(
+ "unexpectedly given multiple inputs or given unknown input");
}
}
diff --git a/flang/include/flang/Frontend/LangOptions.h b/flang/include/flang/Frontend/LangOptions.h
index c8edbfdbc8d1c..7adf2eec9ca3d 100644
--- a/flang/include/flang/Frontend/LangOptions.h
+++ b/flang/include/flang/Frontend/LangOptions.h
@@ -15,6 +15,8 @@
#ifndef LLVM_FLANG_FRONTEND_LANGOPTIONS_H
#define LLVM_FLANG_FRONTEND_LANGOPTIONS_H
+#include <string>
+
namespace Fortran::frontend {
/// Bitfields of LangOptions, split out from LangOptions to ensure
@@ -52,6 +54,10 @@ class LangOptions : public LangOptionsBase {
void set##Name(Type Value) { Name = static_cast<unsigned>(Value); }
#include "flang/Frontend/LangOptions.def"
+ /// Name of the IR file that contains the result of the OpenMP target
+ /// host code generation.
+ std::string OMPHostIRFile;
+
LangOptions();
};
diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h
index 19d31dffaac20..a28b45ca27612 100644
--- a/flang/include/flang/Tools/CrossToolHelpers.h
+++ b/flang/include/flang/Tools/CrossToolHelpers.h
@@ -23,13 +23,14 @@ struct OffloadModuleOpts {
OffloadModuleOpts() {}
OffloadModuleOpts(uint32_t OpenMPTargetDebug, bool OpenMPTeamSubscription,
bool OpenMPThreadSubscription, bool OpenMPNoThreadState,
- bool OpenMPNoNestedParallelism, bool OpenMPIsDevice)
+ bool OpenMPNoNestedParallelism, bool OpenMPIsDevice,
+ std::string OMPHostIRFile = {})
: OpenMPTargetDebug(OpenMPTargetDebug),
OpenMPTeamSubscription(OpenMPTeamSubscription),
OpenMPThreadSubscription(OpenMPThreadSubscription),
OpenMPNoThreadState(OpenMPNoThreadState),
OpenMPNoNestedParallelism(OpenMPNoNestedParallelism),
- OpenMPIsDevice(OpenMPIsDevice) {}
+ OpenMPIsDevice(OpenMPIsDevice), OMPHostIRFile(OMPHostIRFile) {}
OffloadModuleOpts(Fortran::frontend::LangOptions &Opts)
: OpenMPTargetDebug(Opts.OpenMPTargetDebug),
@@ -37,7 +38,8 @@ struct OffloadModuleOpts {
OpenMPThreadSubscription(Opts.OpenMPThreadSubscription),
OpenMPNoThreadState(Opts.OpenMPNoThreadState),
OpenMPNoNestedParallelism(Opts.OpenMPNoNestedParallelism),
- OpenMPIsDevice(Opts.OpenMPIsDevice) {}
+ OpenMPIsDevice(Opts.OpenMPIsDevice), OMPHostIRFile(Opts.OMPHostIRFile) {
+ }
uint32_t OpenMPTargetDebug = 0;
bool OpenMPTeamSubscription = false;
@@ -45,6 +47,7 @@ struct OffloadModuleOpts {
bool OpenMPNoThreadState = false;
bool OpenMPNoNestedParallelism = false;
bool OpenMPIsDevice = false;
+ std::string OMPHostIRFile = {};
};
// Shares assinging of the OpenMP OffloadModuleInterface and its assorted
@@ -59,6 +62,9 @@ void setOffloadModuleInterfaceAttributes(
offloadMod.setFlags(Opts.OpenMPTargetDebug, Opts.OpenMPTeamSubscription,
Opts.OpenMPThreadSubscription, Opts.OpenMPNoThreadState,
Opts.OpenMPNoNestedParallelism);
+
+ if (!Opts.OMPHostIRFile.empty())
+ offloadMod.setHostIRFilePath(Opts.OMPHostIRFile);
}
}
}
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index c6d5152c38d17..6672777f34377 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -726,6 +726,16 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
if (args.hasArg(clang::driver::options::OPT_fopenmp_is_device)) {
res.getLangOpts().OpenMPIsDevice = 1;
+ // Get OpenMP host file path if any and report if a non existent file is
+ // found
+ if (auto *arg = args.getLastArg(
+ clang::driver::options::OPT_fopenmp_host_ir_file_path)) {
+ res.getLangOpts().OMPHostIRFile = arg->getValue();
+ if (!llvm::sys::fs::exists(res.getLangOpts().OMPHostIRFile))
+ diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found)
+ << res.getLangOpts().OMPHostIRFile;
+ }
+
if (args.hasFlag(
clang::driver::options::OPT_fopenmp_assume_teams_oversubscription,
clang::driver::options::
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index f57fd32b0838e..655178677f2ff 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -153,6 +153,8 @@
! HELP-FC1-NEXT: -fno-version-loops-for-stride
! HELP-FC1-NEXT: Do not create unit-strided loops (default)
! HELP-FC1-NEXT: -fopenacc Enable OpenACC
+! HELP-FC1-NEXT: -fopenmp-host-ir-file-path <value>
+! HELP-FC1-NEXT: Path to the IR file produced by the frontend for the host.
! HELP-FC1-NEXT: -fopenmp-is-device Generate code only for an OpenMP target device.
! HELP-FC1-NEXT: -fopenmp-target-debug Enable debugging in the OpenMP offloading device RTL
! HELP-FC1-NEXT: -fopenmp Parse OpenMP pragmas and generate parallel code.
diff --git a/flang/test/Driver/omp-driver-offload.f90 b/flang/test/Driver/omp-driver-offload.f90
index ec107261d4c2b..c5acd930a49e0 100644
--- a/flang/test/Driver/omp-driver-offload.f90
+++ b/flang/test/Driver/omp-driver-offload.f90
@@ -47,15 +47,15 @@
! RUN: %flang -### -fopenmp -fopenmp-targets=amdgcn-amd-amdhsa %s 2>&1 | FileCheck --check-prefixes=CHECK-OPENMP-IS-DEVICE %s
! CHECK-OPENMP-IS-DEVICE: "{{[^"]*}}flang-new" "-fc1" {{.*}} "-fopenmp" {{.*}} "-fopenmp-is-device" {{.*}}.f90"
-! Testing fembed-offload-object and fopenmp-is-device
+! Testing appropriate flags are gnerated and appropriately assigned by the driver when offloading
! RUN: %flang -S -### %s -o %t 2>&1 \
! RUN: -fopenmp --offload-arch=gfx90a \
! RUN: --target=aarch64-unknown-linux-gnu \
-! RUN: | FileCheck %s --check-prefixes=CHECK-OPENMP-EMBED
-! CHECK-OPENMP-EMBED: "{{[^"]*}}flang-new" "-fc1" "-triple" "aarch64-unknown-linux-gnu" {{.*}} "-fopenmp" {{.*}}.f90"
-! CHECK-OPENMP-EMBED-NEXT: "{{[^"]*}}flang-new" "-fc1" "-triple" "amdgcn-amd-amdhsa" {{.*}} "-fopenmp" {{.*}} "-fopenmp-is-device" {{.*}}.f90"
-! CHECK-OPENMP-EMBED: "{{[^"]*}}clang-offload-packager{{.*}} "--image=file={{.*}}.bc,triple=amdgcn-amd-amdhsa,arch=gfx90a,kind=openmp"
-! CHECK-OPENMP-EMBED-NEXT: "{{[^"]*}}flang-new" "-fc1" "-triple" "aarch64-unknown-linux-gnu" {{.*}} "-fopenmp" {{.*}} "-fembed-offload-object={{.*}}.out" {{.*}}.bc"
+! RUN: | FileCheck %s --check-prefix=OPENMP-OFFLOAD-ARGS
+! OPENMP-OFFLOAD-ARGS: "{{[^"]*}}flang-new" "-fc1" "-triple" "aarch64-unknown-linux-gnu" {{.*}} "-fopenmp" {{.*}}.f90"
+! OPENMP-OFFLOAD-ARGS-NEXT: "{{[^"]*}}flang-new" "-fc1" "-triple" "amdgcn-amd-amdhsa" {{.*}} "-fopenmp" {{.*}} "-fopenmp-host-ir-file-path" "{{.*}}.bc" "-fopenmp-is-device" {{.*}}.f90"
+! OPENMP-OFFLOAD-ARGS: "{{[^"]*}}clang-offload-packager" {{.*}} "--image=file={{.*}}.bc,triple=amdgcn-amd-amdhsa,arch=gfx90a,kind=openmp"
+! OPENMP-OFFLOAD-ARGS-NEXT: "{{[^"]*}}flang-new" "-fc1" "-triple" "aarch64-unknown-linux-gnu" {{.*}} "-fopenmp" {{.*}} "-fembed-offload-object={{.*}}.out" {{.*}}.bc"
! Test -fopenmp with offload for RTL Flag Options
! RUN: %flang -### %s -o %t 2>&1 \
@@ -103,3 +103,9 @@
! CHECK-RTL-ALL: "{{[^"]*}}flang-new" "-fc1" {{.*}} "-fopenmp" {{.*}} "-fopenmp-is-device" "-fopenmp-target-debug" "-fopenmp-assume-teams-oversubscription"
! CHECK-RTL-ALL: "-fopenmp-assume-threads-oversubscription" "-fopenmp-assume-no-thread-state" "-fopenmp-assume-no-nested-parallelism"
! CHECK-RTL-ALL: {{.*}}.f90"
+
+! Test diagnostic error when host IR file is non-existent
+! RUN: not %flang_fc1 %s -o %t 2>&1 -fopenmp -fopenmp-is-device \
+! RUN: -fopenmp-host-ir-file-path non-existant-file.bc \
+! RUN: | FileCheck %s --check-prefix=HOST-IR-MISSING
+! HOST-IR-MISSING: error: provided host compiler IR file 'non-existant-file.bc' is required to generate code for OpenMP target regions but cannot be found
diff --git a/flang/test/Lower/OpenMP/omp-host-ir-flag.f90 b/flang/test/Lower/OpenMP/omp-host-ir-flag.f90
new file mode 100644
index 0000000000000..f25a024afb1d5
--- /dev/null
+++ b/flang/test/Lower/OpenMP/omp-host-ir-flag.f90
@@ -0,0 +1,6 @@
+!RUN: %flang_fc1 -emit-llvm-bc -fopenmp -o %t.bc %s 2>&1
+!RUN: %flang_fc1 -emit-mlir -fopenmp -fopenmp-is-device -fopenmp-host-ir-file-path %t.bc -o - %s 2>&1 | FileCheck %s
+
+!CHECK: module attributes {{{.*}}, omp.host_ir_filepath = "{{.*}}.bc", omp.is_device = #omp.isdevice<is_device = true>{{.*}}}
+subroutine omp_subroutine()
+end subroutine omp_subroutine
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
index 0cfdc3707de49..b6a292e212963 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
@@ -71,7 +71,7 @@ def OffloadModuleInterface : OpInterface<"OffloadModuleInterface"> {
InterfaceMethod<
/*description=*/[{
Get the IsDeviceAttr attribute on the current module if it exists and return
- its value, if it doesn't exit it returns false by default.
+ its value, if it doesn't exist it returns false by default.
}],
/*retTy=*/"bool",
/*methodName=*/"getIsDevice",
@@ -138,6 +138,34 @@ def OffloadModuleInterface : OpInterface<"OffloadModuleInterface"> {
targetCPU.str(),
targetFeatures.str()));
}]>,
+ InterfaceMethod<
+ /*description=*/[{
+ Set a StringAttr on the current module containing the host IR file path. This
+ file path is used in two-phase compilation during the device phase to generate
+ device side LLVM IR when lowering MLIR.
+ }],
+ /*retTy=*/"void",
+ /*methodName=*/"setHostIRFilePath",
+ (ins "std::string":$hostIRFilePath), [{}], [{
+ $_op->setAttr(
+ mlir::StringAttr::get($_op->getContext(), llvm::Twine{"omp.host_ir_filepath"}),
+ mlir::StringAttr::get($_op->getContext(), hostIRFilePath));
+ }]>,
+ InterfaceMethod<
+ /*description=*/[{
+ Find the host-ir file path StringAttr from the current module if it exists and
+ return its contained value, if it doesn't exist it returns an empty string. This
+ file path is used in two-phase compilation during the device phase to generate
+ device side LLVM IR when lowering MLIR.
+ }],
+ /*retTy=*/"llvm::StringRef",
+ /*methodName=*/"getHostIRFilePath",
+ (ins), [{}], [{
+ if (Attribute filepath = $_op->getAttr("omp.host_ir_filepath"))
+ if (filepath.isa<mlir::StringAttr>())
+ return filepath.dyn_cast<mlir::StringAttr>().getValue();
+ return {};
+ }]>
];
}
More information about the flang-commits
mailing list