diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h new file mode 100644 --- /dev/null +++ b/flang/include/flang/Tools/CrossToolHelpers.h @@ -0,0 +1,30 @@ +//===-- Tools/CrossToolHelpers.h --------------------------------- *-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 +// +//===----------------------------------------------------------------------===// +// A header file for containing functionallity that is used across Flang tools, +// such as helper functions which apply or generate information needed accross +// tools like bbc and flang-new. +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_TOOLS_CROSS_TOOL_HELPERS_H +#define FORTRAN_TOOLS_CROSS_TOOL_HELPERS_H + +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/IR/BuiltinOps.h" + +// Shares assinging of the OpenMP OffloadModuleInterface and its assorted +// attributes accross Flang tools (bbc/flang) +void setOffloadModuleInterfaceAttributes( + mlir::ModuleOp &module, bool isDevice) { + // Should be registered by the OpenMPDialect + if (auto offloadMod = llvm::dyn_cast( + module.getOperation())) { + offloadMod.setIsDevice(isDevice); + } +} + +#endif // FORTRAN_TOOLS_CROSS_TOOL_HELPERS_H 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 @@ -31,6 +31,7 @@ #include "flang/Semantics/runtime-type-info.h" #include "flang/Semantics/semantics.h" #include "flang/Semantics/unparse-with-symbols.h" +#include "flang/Tools/CrossToolHelpers.h" #include "mlir/IR/Dialect.h" #include "mlir/Parser/Parser.h" @@ -222,7 +223,7 @@ if (ci.getInvocation().getFrontendOpts().features.IsEnabled( Fortran::common::LanguageFeature::OpenMP)) { - mlir::omp::OpenMPDialect::setIsDevice( + setOffloadModuleInterfaceAttributes( *mlirModule, ci.getInvocation().getLangOpts().OpenMPIsDevice); } 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 @@ -37,6 +37,7 @@ #include "flang/Semantics/runtime-type-info.h" #include "flang/Semantics/semantics.h" #include "flang/Semantics/unparse-with-symbols.h" +#include "flang/Tools/CrossToolHelpers.h" #include "flang/Version.inc" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "mlir/IR/AsmState.h" @@ -244,7 +245,7 @@ burnside.lower(parseTree, semanticsContext); mlir::ModuleOp mlirModule = burnside.getModule(); if (enableOpenMP) - mlir::omp::OpenMPDialect::setIsDevice(mlirModule, enableOpenMPDevice); + setOffloadModuleInterfaceAttributes(mlirModule, 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 @@ -58,6 +58,10 @@ LLVM::LLVMPointerType::attachInterface< PointerLikeModel>(*getContext()); MemRefType::attachInterface>(*getContext()); + LLVM::LLVMPointerType::attachInterface< + PointerLikeModel>(*getContext()); + mlir::ModuleOp::attachInterface( + *getContext()); } //===----------------------------------------------------------------------===// @@ -1417,26 +1421,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"