diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -222,8 +222,13 @@ if (ci.getInvocation().getFrontendOpts().features.IsEnabled( Fortran::common::LanguageFeature::OpenMP)) { - mlir::omp::OpenMPDialect::setIsDevice( - *mlirModule, ci.getInvocation().getLangOpts().OpenMPIsDevice); + mlir::ModuleOp::attachInterface( + *mlirModule->getContext()); + + if (auto offloadMod = llvm::dyn_cast( + mlirModule->getOperation())) { + offloadMod.setIsDevice(ci.getInvocation().getLangOpts().OpenMPIsDevice); + } } if (!setUpTargetMachine()) diff --git a/flang/test/Lower/OpenMP/omp-is-device.f90 b/flang/test/Lower/OpenMP/omp-is-device.f90 --- a/flang/test/Lower/OpenMP/omp-is-device.f90 +++ b/flang/test/Lower/OpenMP/omp-is-device.f90 @@ -5,10 +5,10 @@ !RUN: bbc -fopenmp -emit-fir -o - %s | FileCheck %s --check-prefix=HOST !RUN: bbc -fopenmp-is-device -emit-fir -o - %s | FileCheck %s --check-prefix=DEVICE-FLAG-ONLY -!DEVICE: module attributes {{{.*}}, omp.is_device = true{{.*}}} -!HOST: module attributes {{{.*}}, omp.is_device = false{{.*}}} +!DEVICE: module attributes {{{.*}}, omp.is_device = #omp.isdevice{{.*}}} +!HOST: module attributes {{{.*}}, omp.is_device = #omp.isdevice{{.*}}} !DEVICE-FLAG-ONLY: module attributes {{{.*}}" -!DEVICE-FLAG-ONLY-NOT: , omp.is_device = {{.*}} +!DEVICE-FLAG-ONLY-NOT: , omp.is_device = #omp.isdevice<{{.*}}> !DEVICE-FLAG-ONLY-SAME: } subroutine omp_subroutine() end subroutine omp_subroutine diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp --- a/flang/tools/bbc/bbc.cpp +++ b/flang/tools/bbc/bbc.cpp @@ -243,8 +243,14 @@ kindMap, loweringOptions, {}); burnside.lower(parseTree, semanticsContext); mlir::ModuleOp mlirModule = burnside.getModule(); - if (enableOpenMP) - mlir::omp::OpenMPDialect::setIsDevice(mlirModule, enableOpenMPDevice); + if (enableOpenMP) { + mlir::ModuleOp::attachInterface( + *mlirModule.getContext()); + if (auto offloadMod = + mlir::dyn_cast(*mlirModule)) { + offloadMod.setIsDevice(enableOpenMPDevice); + } + } std::error_code ec; std::string outputName = outputFilename; if (!outputName.size()) diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h @@ -23,12 +23,13 @@ #include "mlir/Dialect/OpenMP/OpenMPOpsDialect.h.inc" #include "mlir/Dialect/OpenMP/OpenMPOpsEnums.h.inc" -#include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.h.inc" #include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.h.inc" #define GET_ATTRDEF_CLASSES #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.h.inc" +#include "mlir/Dialect/OpenMP/OpenMPInterfaces.h" + #define GET_OP_CLASSES #include "mlir/Dialect/OpenMP/OpenMPOps.h.inc" diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPInterfaces.h copy from mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h copy to mlir/include/mlir/Dialect/OpenMP/OpenMPInterfaces.h --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPInterfaces.h @@ -1,4 +1,4 @@ -//===- OpenMPDialect.h - MLIR Dialect for OpenMP ----------------*- C++ -*-===// +//===- OpenMPInterfaces.h - MLIR Interfaces for OpenMP ----------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// // -// This file declares the OpenMP dialect in MLIR. +// This file declares OpenMP Interface implementations for the OpenMP dialect. // //===----------------------------------------------------------------------===// -#ifndef MLIR_DIALECT_OPENMP_OPENMPDIALECT_H_ -#define MLIR_DIALECT_OPENMP_OPENMPDIALECT_H_ +#ifndef MLIR_DIALECT_OPENMP_OPENMPINTERFACES_H_ +#define MLIR_DIALECT_OPENMP_OPENMPINTERFACES_H_ #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/IR/Dialect.h" @@ -21,15 +21,15 @@ #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/SideEffectInterfaces.h" -#include "mlir/Dialect/OpenMP/OpenMPOpsDialect.h.inc" -#include "mlir/Dialect/OpenMP/OpenMPOpsEnums.h.inc" #include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.h.inc" -#include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.h.inc" -#define GET_ATTRDEF_CLASSES -#include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.h.inc" +namespace mlir::omp { +// You can override defaults here or implement more complex implementations of +// functions. Or define a completely seperate external model implementation, +// to override the existing implementation. +struct OffloadModuleDefaultModel + : public OffloadModuleInterface::ExternalModel {}; +} // namespace mlir::omp -#define GET_OP_CLASSES -#include "mlir/Dialect/OpenMP/OpenMPOps.h.inc" - -#endif // MLIR_DIALECT_OPENMP_OPENMPDIALECT_H_ +#endif // MLIR_DIALECT_OPENMP_OPENMPINTERFACES_H_ diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -28,20 +28,30 @@ let cppNamespace = "::mlir::omp"; let dependentDialects = ["::mlir::LLVM::LLVMDialect"]; let useDefaultAttributePrinterParser = 1; - - let extraClassDeclaration = [{ - // Set the omp.is_device attribute on the module with the specified boolean - static void setIsDevice(Operation* module, bool isDevice); - - // Return the value of the omp.is_device attribute stored in the module if it - // exists, otherwise return false by default - static bool getIsDevice(Operation* module); - }]; } // OmpCommon requires definition of OpenACC_Dialect. include "mlir/Dialect/OpenMP/OmpCommon.td" +//===----------------------------------------------------------------------===// +// OpenMP Attributes +//===----------------------------------------------------------------------===// + +class OpenMP_Attr traits = [], + string baseCppClass = "::mlir::Attribute"> + : AttrDef { + let mnemonic = attrMnemonic; +} + +def IsDeviceAttr : OpenMP_Attr<"IsDevice", "isdevice"> { + let parameters = (ins + "bool":$is_device + ); + + let assemblyFormat = "`<` struct(params) `>`"; +} + class OpenMP_Op traits = []> : Op; diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td @@ -47,4 +47,40 @@ ]; } +def OffloadModuleInterface : OpInterface<"OffloadModuleInterface"> { + let description = [{ + Operations that represent a module for offloading (host or device) + should have this interface. + }]; + + let cppNamespace = "::mlir::omp"; + + let methods = [ + InterfaceMethod< + /*description=*/[{ + Set the attribute IsDeviceAttr on the current module with the + specified boolean argument. + }], + /*retTy=*/"void", + /*methodName=*/"setIsDevice", + (ins "bool":$isDevice), [{}], [{ + $_op->setAttr( + mlir::StringAttr::get($_op->getContext(), llvm::Twine{"omp.is_device"}), + mlir::omp::IsDeviceAttr::get($_op->getContext(), isDevice)); + }]>, + 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. + }], + /*retTy=*/"bool", + /*methodName=*/"getIsDevice", + (ins), [{}], [{ + if (Attribute isDevice = $_op->getAttr("omp.is_device")) + if (isDevice.isa()) + return isDevice.dyn_cast().getIsDevice(); + }]>, + ]; +} + #endif // OpenMP_OPS_INTERFACES diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -1417,26 +1417,6 @@ return success(); } -//===----------------------------------------------------------------------===// -// OpenMPDialect helper functions -//===----------------------------------------------------------------------===// - -// Set the omp.is_device attribute on the module with the specified boolean -void OpenMPDialect::setIsDevice(Operation* module, bool isDevice) { - module->setAttr( - mlir::StringAttr::get(module->getContext(), llvm::Twine{"omp.is_device"}), - mlir::BoolAttr::get(module->getContext(), isDevice)); -} - -// Return the value of the omp.is_device attribute stored in the module if it -// exists, otherwise return false by default -bool OpenMPDialect::getIsDevice(Operation* module) { - if (Attribute isDevice = module->getAttr("omp.is_device")) - if (isDevice.isa()) - return isDevice.dyn_cast().getValue(); - return false; -} - #define GET_ATTRDEF_CLASSES #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"