Skip to content

Commit

Permalink
Revert "Revert "[Flang][OpenMP][MLIR] Add declare target attribute se…
Browse files Browse the repository at this point in the history
…t and interface for the OpenMP dialect""

This reverts commit aa6b47c.

And adds a fix (adding missing libraries
to CMakeLists.txt for the OpenMPDialect)
that allows failing builds to succeed.
  • Loading branch information
agozillon committed May 22, 2023
1 parent 481b254 commit 231a695
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 1 deletion.
3 changes: 3 additions & 0 deletions flang/include/flang/Optimizer/Dialect/FIRDialect.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ class FIROpsDialect final : public mlir::Dialect {
void registerAttributes();
// Register the Types of this dialect.
void registerTypes();
// Register external interfaces on operations of
// this dialect.
void registerOpExternalInterfaces();
};

/// The FIR codegen dialect is a dialect containing a small set of transient
Expand Down
1 change: 1 addition & 0 deletions flang/lib/Optimizer/Dialect/FIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ fir::FIROpsDialect::FIROpsDialect(mlir::MLIRContext *ctx)
#define GET_OP_LIST
#include "flang/Optimizer/Dialect/FIROps.cpp.inc"
>();
registerOpExternalInterfaces();
addInterfaces<FIRInlinerInterface>();
}

Expand Down
13 changes: 13 additions & 0 deletions flang/lib/Optimizer/Dialect/FIROps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@

#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
#include "flang/Optimizer/Support/Utils.h"
#include "mlir/Dialect/CommonFolders.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
Expand Down Expand Up @@ -3758,6 +3760,17 @@ mlir::LogicalResult fir::DeclareOp::verify() {
return fortranVar.verifyDeclareLikeOpImpl(getMemref());
}

//===----------------------------------------------------------------------===//
// FIROpsDialect
//===----------------------------------------------------------------------===//

void fir::FIROpsDialect::registerOpExternalInterfaces() {
// Attach default declare target interfaces to operations which can be marked
// as declare target.
fir::GlobalOp::attachInterface<
mlir::omp::DeclareTargetDefaultModel<fir::GlobalOp>>(*getContext());
}

// Tablegen operators

#define GET_OP_CLASSES
Expand Down
78 changes: 78 additions & 0 deletions flang/test/Fir/omp-declare-target-data.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// RUN: fir-opt --fir-to-llvm-ir %s | FileCheck %s

module attributes {omp.is_device = #omp.isdevice<is_device = false>} {

// CHECK: llvm.mlir.global external @_QMtest_0Earray_1d(dense<[1, 2, 3]> : tensor<3xi32>) {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>{{.*}}} : !llvm.array<3 x i32>
fir.global @_QMtest_0Earray_1d(dense<[1, 2, 3]> : tensor<3xi32>) {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} : !fir.array<3xi32>

// CHECK: llvm.mlir.global external @_QMtest_0Earray_2d() {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>{{.*}}} : !llvm.array<2 x array<2 x i32>>
fir.global @_QMtest_0Earray_2d {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} : !fir.array<2x2xi32> {
%0 = fir.undefined !fir.array<2x2xi32>
%c1_i32 = arith.constant 1 : i32
%1 = fir.insert_value %0, %c1_i32, [0 : index, 0 : index] : (!fir.array<2x2xi32>, i32) -> !fir.array<2x2xi32>
%c2_i32 = arith.constant 2 : i32
%2 = fir.insert_value %1, %c2_i32, [1 : index, 0 : index] : (!fir.array<2x2xi32>, i32) -> !fir.array<2x2xi32>
%c3_i32 = arith.constant 3 : i32
%3 = fir.insert_value %2, %c3_i32, [0 : index, 1 : index] : (!fir.array<2x2xi32>, i32) -> !fir.array<2x2xi32>
%c4_i32 = arith.constant 4 : i32
%4 = fir.insert_value %3, %c4_i32, [1 : index, 1 : index] : (!fir.array<2x2xi32>, i32) -> !fir.array<2x2xi32>
%c2 = arith.constant 2 : index
%c2_0 = arith.constant 2 : index
fir.has_value %4 : !fir.array<2x2xi32>
}

// CHECK: llvm.mlir.global external @_QMtest_0Edata_extended_link_1() {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>{{.*}}} : f32
fir.global @_QMtest_0Edata_extended_link_1 {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} : f32 {
%cst = arith.constant 2.000000e+00 : f32
fir.has_value %cst : f32
}

// CHECK: llvm.mlir.global external @_QMtest_0Edata_extended_link_2() {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>{{.*}}} : f32
fir.global @_QMtest_0Edata_extended_link_2 {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} : f32 {
%cst = arith.constant 3.000000e+00 : f32
fir.has_value %cst : f32
}

// CHECK: llvm.mlir.global external @_QMtest_0Edata_extended_to_1() {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>{{.*}}} : f32
fir.global @_QMtest_0Edata_extended_to_1 {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>} : f32 {
%cst = arith.constant 2.000000e+00 : f32
fir.has_value %cst : f32
}

// CHECK: llvm.mlir.global external @_QMtest_0Edata_extended_to_2() {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>{{.*}}} : f32 {
fir.global @_QMtest_0Edata_extended_to_2 {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>} : f32 {
%cst = arith.constant 3.000000e+00 : f32
fir.has_value %cst : f32
}

// CHECK: llvm.mlir.global external @_QMtest_0Edata_int() {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>{{.*}}} : i32
fir.global @_QMtest_0Edata_int {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} : i32 {
%c10_i32 = arith.constant 10 : i32
fir.has_value %c10_i32 : i32
}

// CHECK: llvm.mlir.global external @_QMtest_0Edata_int_clauseless() {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>{{.*}}} : i32
fir.global @_QMtest_0Edata_int_clauseless {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>} : i32 {
%c1_i32 = arith.constant 1 : i32
fir.has_value %c1_i32 : i32
}

// CHECK: llvm.mlir.global external @_QMtest_0Edata_int_to() {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>{{.*}}} : i32
fir.global @_QMtest_0Edata_int_to {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>} : i32 {
%c5_i32 = arith.constant 5 : i32
fir.has_value %c5_i32 : i32
}

// CHECK: llvm.mlir.global external @_QMtest_0Ept1() {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>{{.*}}} : !llvm.struct<(ptr<i32>, i64, i32, i8, i8, i8, i8)> {
fir.global @_QMtest_0Ept1 {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} : !fir.box<!fir.ptr<i32>> {
%0 = fir.zero_bits !fir.ptr<i32>
%1 = fir.embox %0 : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
fir.has_value %1 : !fir.box<!fir.ptr<i32>>
}

// CHECK: llvm.mlir.global external @_QMtest_0Ept2_tar() {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>{{.*}}} : i32
fir.global @_QMtest_0Ept2_tar {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} target : i32 {
%c5_i32 = arith.constant 5 : i32
fir.has_value %c5_i32 : i32
}
}
6 changes: 6 additions & 0 deletions mlir/include/mlir/Dialect/OpenMP/OpenMPInterfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ namespace mlir::omp {
struct OffloadModuleDefaultModel
: public OffloadModuleInterface::ExternalModel<OffloadModuleDefaultModel,
mlir::ModuleOp> {};

template <typename T>
struct DeclareTargetDefaultModel
: public DeclareTargetInterface::ExternalModel<DeclareTargetDefaultModel<T>,
T> {};

} // namespace mlir::omp

#endif // MLIR_DIALECT_OPENMP_OPENMPINTERFACES_H_
48 changes: 47 additions & 1 deletion mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.td"
def OpenMP_Dialect : Dialect {
let name = "omp";
let cppNamespace = "::mlir::omp";
let dependentDialects = ["::mlir::LLVM::LLVMDialect"];
let dependentDialects = ["::mlir::LLVM::LLVMDialect, ::mlir::func::FuncDialect"];
let useDefaultAttributePrinterParser = 1;
let usePropertiesForAttributes = 1;
}
Expand Down Expand Up @@ -97,6 +97,52 @@ def IntLikeType : AnyTypeOf<[AnyInteger, Index]>;
def OpenMP_PointerLikeType : TypeAlias<OpenMP_PointerLikeTypeInterface,
"OpenMP-compatible variable type">;

//===----------------------------------------------------------------------===//
// 2.12.7 Declare Target Directive
//===----------------------------------------------------------------------===//

def DeviceTypeAny : I32EnumAttrCase<"any", 0>;
def DeviceTypeHost : I32EnumAttrCase<"host", 1>;
def DeviceTypeNoHost : I32EnumAttrCase<"nohost", 2>;

def DeclareTargetDeviceType : I32EnumAttr<
"DeclareTargetDeviceType",
"device_type clause",
[DeviceTypeAny, DeviceTypeHost, DeviceTypeNoHost]> {
let genSpecializedAttr = 0;
let cppNamespace = "::mlir::omp";
}

def DeclareTargetDeviceTypeAttr : EnumAttr<OpenMP_Dialect, DeclareTargetDeviceType,
"device_type"> {
let assemblyFormat = "`(` $value `)`";
}

def CaptureClauseLink : I32EnumAttrCase<"to", 0>;
def CaptureClauseTo : I32EnumAttrCase<"link", 1>;

def DeclareTargetCaptureClause : I32EnumAttr<
"DeclareTargetCaptureClause",
"capture clause",
[CaptureClauseLink, CaptureClauseTo]> {
let genSpecializedAttr = 0;
let cppNamespace = "::mlir::omp";
}

def DeclareTargetCaptureClauseAttr : EnumAttr<OpenMP_Dialect, DeclareTargetCaptureClause,
"capture_clause"> {
let assemblyFormat = "`(` $value `)`";
}

def DeclareTargetAttr : OpenMP_Attr<"DeclareTarget", "declaretarget"> {
let parameters = (ins
OptionalParameter<"DeclareTargetDeviceTypeAttr">:$device_type,
OptionalParameter<"DeclareTargetCaptureClauseAttr">:$capture_clause
);

let assemblyFormat = "`<` struct(params) `>`";
}

//===----------------------------------------------------------------------===//
// 2.6 parallel Construct
//===----------------------------------------------------------------------===//
Expand Down
68 changes: 68 additions & 0 deletions mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,74 @@ def ReductionClauseInterface : OpInterface<"ReductionClauseInterface"> {
];
}

def DeclareTargetInterface : OpInterface<"DeclareTargetInterface"> {
let description = [{
OpenMP operations that support declare target have this interface.
For example, FuncOp's and llvm.GlobalOp/fir.GlobalOp's. This
interface allows simple manipulation and introspection of the
declare target attribute that can be applied to these operations.
}];

let cppNamespace = "::mlir::omp";

let methods = [
InterfaceMethod<
/*description=*/[{
Set the declare target attribute on the current operation with the
specified attribute arguments.
}],
/*retTy=*/"void",
/*methodName=*/"setDeclareTarget",
(ins "mlir::omp::DeclareTargetDeviceType":$deviceType,
"mlir::omp::DeclareTargetCaptureClause":$captureClause), [{}], [{
$_op->setAttr("omp.declare_target",
mlir::omp::DeclareTargetAttr::get(
$_op->getContext(),
mlir::omp::DeclareTargetDeviceTypeAttr::get(
$_op->getContext(), deviceType),
mlir::omp::DeclareTargetCaptureClauseAttr::get(
$_op->getContext(), captureClause)));
}]>,
InterfaceMethod<
/*description=*/[{
Checks if the declare target attribute has been applied and exists on the
current operation. Returns true if it exists on it, otherwise returns
false.
}],
/*retTy=*/"bool",
/*methodName=*/"isDeclareTarget",
(ins), [{}], [{
return $_op->hasAttr("omp.declare_target");
}]>,
InterfaceMethod<
/*description=*/[{
Returns the DeclareTargetDeviceType segment of the DeclareTarget attribute if it
exists on the current operation. Otherwise it returns null.
}],
/*retTy=*/"mlir::omp::DeclareTargetDeviceType",
/*methodName=*/"getDeclareTargetDeviceType",
(ins), [{}], [{
if (mlir::Attribute dTar = $_op->getAttr("omp.declare_target"))
if (auto dAttr = dTar.dyn_cast_or_null<mlir::omp::DeclareTargetAttr>())
return dAttr.getDeviceType().getValue();
return {};
}]>,
InterfaceMethod<
/*description=*/[{
Returns the DeclareTargetCaptureClause segment of the DeclareTarget attribute if it
exists on the current operation. Otherwise it returns null.
}],
/*retTy=*/"mlir::omp::DeclareTargetCaptureClause",
/*methodName=*/"getDeclareTargetCaptureClause",
(ins), [{}], [{
if (mlir::Attribute dTar = $_op->getAttr("omp.declare_target"))
if (auto dAttr = dTar.dyn_cast_or_null<mlir::omp::DeclareTargetAttr>())
return dAttr.getCaptureClause().getValue();
return {};
}]>
];
}

def OffloadModuleInterface : OpInterface<"OffloadModuleInterface"> {
let description = [{
Operations that represent a module for offloading (host or device)
Expand Down
1 change: 1 addition & 0 deletions mlir/lib/Dialect/OpenMP/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ add_mlir_dialect_library(MLIROpenMPDialect
LINK_LIBS PUBLIC
MLIRIR
MLIRLLVMDialect
MLIRFuncDialect
)
16 changes: 16 additions & 0 deletions mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/DialectImplementation.h"
Expand Down Expand Up @@ -71,8 +72,23 @@ void OpenMPDialect::initialize() {
MemRefType::attachInterface<PointerLikeModel<MemRefType>>(*getContext());
LLVM::LLVMPointerType::attachInterface<
PointerLikeModel<LLVM::LLVMPointerType>>(*getContext());

// Attach default offload module interface to module op to access
// offload functionality through
mlir::ModuleOp::attachInterface<mlir::omp::OffloadModuleDefaultModel>(
*getContext());

// Attach default declare target interfaces to operations which can be marked
// as declare target (Global Operations and Functions/Subroutines in dialects
// that Fortran (or other languages that lower to MLIR) translates too
mlir::LLVM::GlobalOp::attachInterface<
mlir::omp::DeclareTargetDefaultModel<mlir::LLVM::GlobalOp>>(
*getContext());
mlir::LLVM::LLVMFuncOp::attachInterface<
mlir::omp::DeclareTargetDefaultModel<mlir::LLVM::LLVMFuncOp>>(
*getContext());
mlir::func::FuncOp::attachInterface<
mlir::omp::DeclareTargetDefaultModel<mlir::func::FuncOp>>(*getContext());
}

//===----------------------------------------------------------------------===//
Expand Down

0 comments on commit 231a695

Please sign in to comment.