[NFC][OpenMP][mlir][flang] Move OMP offloading module attribute handling from flang to mlir (#186409)

This patch moves the OpenMP offloding module attributes handling from
flang to mlir so that it can be reused in ClangIR was well.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Michael Kruse <github@meinersbur.de>
This commit is contained in:
Jan Leyonberg 2026-03-25 16:08:32 -04:00 committed by GitHub
parent b491bd9826
commit d7e60d5250
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 127 additions and 93 deletions

View File

@ -157,89 +157,15 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
Fortran::common::FPMaxminBehavior::Legacy;
};
struct OffloadModuleOpts {
OffloadModuleOpts() {}
OffloadModuleOpts(uint32_t OpenMPTargetDebug, bool OpenMPTeamSubscription,
bool OpenMPThreadSubscription, bool OpenMPNoThreadState,
bool OpenMPNoNestedParallelism, bool OpenMPIsTargetDevice,
bool OpenMPIsGPU, bool OpenMPForceUSM, uint32_t OpenMPVersion,
std::string OMPHostIRFile = {},
const std::vector<llvm::Triple> &OMPTargetTriples = {},
bool NoGPULib = false)
: OpenMPTargetDebug(OpenMPTargetDebug),
OpenMPTeamSubscription(OpenMPTeamSubscription),
OpenMPThreadSubscription(OpenMPThreadSubscription),
OpenMPNoThreadState(OpenMPNoThreadState),
OpenMPNoNestedParallelism(OpenMPNoNestedParallelism),
OpenMPIsTargetDevice(OpenMPIsTargetDevice), OpenMPIsGPU(OpenMPIsGPU),
OpenMPForceUSM(OpenMPForceUSM), OpenMPVersion(OpenMPVersion),
OMPHostIRFile(OMPHostIRFile),
OMPTargetTriples(OMPTargetTriples.begin(), OMPTargetTriples.end()),
NoGPULib(NoGPULib) {}
OffloadModuleOpts(Fortran::common::LangOptions &Opts)
: OpenMPTargetDebug(Opts.OpenMPTargetDebug),
OpenMPTeamSubscription(Opts.OpenMPTeamSubscription),
OpenMPThreadSubscription(Opts.OpenMPThreadSubscription),
OpenMPNoThreadState(Opts.OpenMPNoThreadState),
OpenMPNoNestedParallelism(Opts.OpenMPNoNestedParallelism),
OpenMPIsTargetDevice(Opts.OpenMPIsTargetDevice),
OpenMPIsGPU(Opts.OpenMPIsGPU), OpenMPForceUSM(Opts.OpenMPForceUSM),
OpenMPVersion(Opts.OpenMPVersion), OMPHostIRFile(Opts.OMPHostIRFile),
OMPTargetTriples(Opts.OMPTargetTriples), NoGPULib(Opts.NoGPULib) {}
uint32_t OpenMPTargetDebug = 0;
bool OpenMPTeamSubscription = false;
bool OpenMPThreadSubscription = false;
bool OpenMPNoThreadState = false;
bool OpenMPNoNestedParallelism = false;
bool OpenMPIsTargetDevice = false;
bool OpenMPIsGPU = false;
bool OpenMPForceUSM = false;
uint32_t OpenMPVersion = 31;
std::string OMPHostIRFile = {};
std::vector<llvm::Triple> OMPTargetTriples = {};
bool NoGPULib = false;
};
// Shares assinging of the OpenMP OffloadModuleInterface and its assorted
// attributes accross Flang tools (bbc/flang)
[[maybe_unused]] static void setOffloadModuleInterfaceAttributes(
mlir::ModuleOp module, OffloadModuleOpts Opts) {
// Should be registered by the OpenMPDialect
if (auto offloadMod = llvm::dyn_cast<mlir::omp::OffloadModuleInterface>(
module.getOperation())) {
offloadMod.setIsTargetDevice(Opts.OpenMPIsTargetDevice);
offloadMod.setIsGPU(Opts.OpenMPIsGPU);
if (Opts.OpenMPForceUSM) {
offloadMod.setRequires(mlir::omp::ClauseRequires::unified_shared_memory);
}
if (Opts.OpenMPIsTargetDevice) {
offloadMod.setFlags(Opts.OpenMPTargetDebug, Opts.OpenMPTeamSubscription,
Opts.OpenMPThreadSubscription, Opts.OpenMPNoThreadState,
Opts.OpenMPNoNestedParallelism, Opts.OpenMPVersion, Opts.NoGPULib);
if (!Opts.OMPHostIRFile.empty())
offloadMod.setHostIRFilePath(Opts.OMPHostIRFile);
}
auto strTriples = llvm::to_vector(llvm::map_range(Opts.OMPTargetTriples,
[](llvm::Triple triple) { return triple.normalize(); }));
offloadMod.setTargetTriples(strTriples);
}
}
[[maybe_unused]] static void setOpenMPVersionAttribute(
mlir::ModuleOp module, int64_t version) {
module.getOperation()->setAttr(
mlir::StringAttr::get(module.getContext(), llvm::Twine{"omp.version"}),
mlir::omp::VersionAttr::get(module.getContext(), version));
}
[[maybe_unused]] static int64_t getOpenMPVersionAttribute(
mlir::ModuleOp module, int64_t fallback = -1) {
if (mlir::Attribute verAttr = module->getAttr("omp.version"))
return llvm::cast<mlir::omp::VersionAttr>(verAttr).getVersion();
return fallback;
/// Create OffloadModuleOpts from Flang LangOptions.
[[maybe_unused]] static mlir::omp::OffloadModuleOpts makeOffloadModuleOpts(
Fortran::common::LangOptions &Opts) {
return mlir::omp::OffloadModuleOpts(Opts.OpenMPTargetDebug,
Opts.OpenMPTeamSubscription, Opts.OpenMPThreadSubscription,
Opts.OpenMPNoThreadState, Opts.OpenMPNoNestedParallelism,
Opts.OpenMPIsTargetDevice, Opts.OpenMPIsGPU, Opts.OpenMPForceUSM,
Opts.OpenMPVersion, Opts.OMPHostIRFile, Opts.OMPTargetTriples,
Opts.NoGPULib);
}
#endif // FORTRAN_TOOLS_CROSS_TOOL_HELPERS_H

View File

@ -273,10 +273,11 @@ bool CodeGenAction::beginSourceFileAction() {
if (ci.getInvocation().getFrontendOpts().features.IsEnabled(
Fortran::common::LanguageFeature::OpenMP)) {
setOffloadModuleInterfaceAttributes(lb.getModule(),
ci.getInvocation().getLangOpts());
setOpenMPVersionAttribute(lb.getModule(),
ci.getInvocation().getLangOpts().OpenMPVersion);
mlir::omp::setOffloadModuleInterfaceAttributes(
lb.getModule(),
makeOffloadModuleOpts(ci.getInvocation().getLangOpts()));
mlir::omp::setOpenMPVersionAttribute(
lb.getModule(), ci.getInvocation().getLangOpts().OpenMPVersion);
}
if (ci.getInvocation().getLangOpts().FastRealMod) {

View File

@ -42,9 +42,9 @@ struct ConstructDecomposition {
llvm::omp::Directive compound,
const List<Clause> &clauses)
: semaCtx(semaCtx), mod(modOp), eval(ev) {
tomp::ConstructDecompositionT decompose(getOpenMPVersionAttribute(modOp),
*this, compound,
llvm::ArrayRef(clauses));
tomp::ConstructDecompositionT decompose(
mlir::omp::getOpenMPVersionAttribute(modOp), *this, compound,
llvm::ArrayRef(clauses));
output = std::move(decompose.output);
}

View File

@ -502,13 +502,14 @@ static llvm::LogicalResult convertFortranSourceToMLIR(
for (llvm::StringRef s : targetTriplesOpenMP)
targetTriples.emplace_back(s);
auto offloadModuleOpts = OffloadModuleOpts(
auto offloadModuleOpts = mlir::omp::OffloadModuleOpts(
setOpenMPTargetDebug, setOpenMPTeamSubscription,
setOpenMPThreadSubscription, setOpenMPNoThreadState,
setOpenMPNoNestedParallelism, enableOpenMPDevice, enableOpenMPGPU,
enableOpenMPForceUSM, setOpenMPVersion, "", targetTriples, setNoGPULib);
setOffloadModuleInterfaceAttributes(mlirModule, offloadModuleOpts);
setOpenMPVersionAttribute(mlirModule, setOpenMPVersion);
mlir::omp::setOffloadModuleInterfaceAttributes(mlirModule,
offloadModuleOpts);
mlir::omp::setOpenMPVersionAttribute(mlirModule, setOpenMPVersion);
}
burnside.lower(parseTree, semanticsContext);
std::error_code ec;

View File

@ -17,6 +17,7 @@
#include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.h"
#include "mlir/Dialect/OpenACCMPCommon/Interfaces/OpenACCMPOpsInterfaces.h"
#include "mlir/Dialect/OpenMP/OpenMPInterfaces.h"
#include "mlir/Dialect/OpenMP/OpenMPOffloadUtils.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/PatternMatch.h"

View File

@ -0,0 +1,105 @@
//===- OpenMPOffloadUtils.h - OpenMP offload utilities ----------*- 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
//
//===----------------------------------------------------------------------===//
//
/// \file
/// Shared utilities for setting OpenMP offload module interface attributes.
/// These are used by both Flang and Clang (CIR) frontends.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_DIALECT_OPENMP_OPENMPOFFLOADUTILS_H_
#define MLIR_DIALECT_OPENMP_OPENMPOFFLOADUTILS_H_
#include "mlir/Dialect/OpenMP/OpenMPInterfaces.h"
#include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/TargetParser/Triple.h"
#include <cstdint>
#include <string>
#include <vector>
namespace mlir::omp {
struct OffloadModuleOpts {
OffloadModuleOpts() = default;
OffloadModuleOpts(uint32_t openMPTargetDebug, bool openMPTeamSubscription,
bool openMPThreadSubscription, bool openMPNoThreadState,
bool openMPNoNestedParallelism, bool openMPIsTargetDevice,
bool openMPIsGPU, bool openMPForceUSM,
uint32_t openMPVersion, std::string ompHostIRFile = {},
const std::vector<llvm::Triple> &ompTargetTriples = {},
bool noGPULib = false)
: OpenMPTargetDebug(openMPTargetDebug),
OpenMPTeamSubscription(openMPTeamSubscription),
OpenMPThreadSubscription(openMPThreadSubscription),
OpenMPNoThreadState(openMPNoThreadState),
OpenMPNoNestedParallelism(openMPNoNestedParallelism),
OpenMPIsTargetDevice(openMPIsTargetDevice), OpenMPIsGPU(openMPIsGPU),
OpenMPForceUSM(openMPForceUSM), OpenMPVersion(openMPVersion),
OMPHostIRFile(std::move(ompHostIRFile)),
OMPTargetTriples(ompTargetTriples.begin(), ompTargetTriples.end()),
NoGPULib(noGPULib) {}
uint32_t OpenMPTargetDebug = 0;
bool OpenMPTeamSubscription = false;
bool OpenMPThreadSubscription = false;
bool OpenMPNoThreadState = false;
bool OpenMPNoNestedParallelism = false;
bool OpenMPIsTargetDevice = false;
bool OpenMPIsGPU = false;
bool OpenMPForceUSM = false;
uint32_t OpenMPVersion = 31;
std::string OMPHostIRFile = {};
std::vector<llvm::Triple> OMPTargetTriples = {};
bool NoGPULib = false;
};
/// Sets OpenMP offload module interface attributes on a ModuleOp, shared
/// between Flang and Clang (CIR) frontends.
[[maybe_unused]] static void
setOffloadModuleInterfaceAttributes(ModuleOp module, OffloadModuleOpts opts) {
if (auto offloadMod =
llvm::dyn_cast<OffloadModuleInterface>(module.getOperation())) {
offloadMod.setIsTargetDevice(opts.OpenMPIsTargetDevice);
offloadMod.setIsGPU(opts.OpenMPIsGPU);
if (opts.OpenMPForceUSM)
offloadMod.setRequires(ClauseRequires::unified_shared_memory);
if (opts.OpenMPIsTargetDevice) {
offloadMod.setFlags(
opts.OpenMPTargetDebug, opts.OpenMPTeamSubscription,
opts.OpenMPThreadSubscription, opts.OpenMPNoThreadState,
opts.OpenMPNoNestedParallelism, opts.OpenMPVersion, opts.NoGPULib);
if (!opts.OMPHostIRFile.empty())
offloadMod.setHostIRFilePath(opts.OMPHostIRFile);
}
auto strTriples = llvm::to_vector(
llvm::map_range(opts.OMPTargetTriples, [](llvm::Triple triple) {
return triple.normalize();
}));
offloadMod.setTargetTriples(strTriples);
}
}
[[maybe_unused]] static void setOpenMPVersionAttribute(ModuleOp module,
int64_t version) {
module.getOperation()->setAttr(
StringAttr::get(module.getContext(), llvm::Twine{"omp.version"}),
VersionAttr::get(module.getContext(), version));
}
[[maybe_unused]] static int64_t
getOpenMPVersionAttribute(ModuleOp module, int64_t fallback = -1) {
if (Attribute verAttr = module->getAttr("omp.version"))
return llvm::cast<VersionAttr>(verAttr).getVersion();
return fallback;
}
} // namespace mlir::omp
#endif // MLIR_DIALECT_OPENMP_OPENMPOFFLOADUTILS_H_