diff --git a/mlir/include/mlir/Dialect/CMakeLists.txt b/mlir/include/mlir/Dialect/CMakeLists.txt --- a/mlir/include/mlir/Dialect/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(Func) add_subdirectory(GPU) add_subdirectory(Index) +add_subdirectory(IRDL) add_subdirectory(LLVMIR) add_subdirectory(Linalg) add_subdirectory(MLProgram) diff --git a/mlir/include/mlir/Dialect/IRDL/CMakeLists.txt b/mlir/include/mlir/Dialect/IRDL/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/IRDL/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(IR) diff --git a/mlir/include/mlir/Dialect/IRDL/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/IRDL/IR/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/IRDL/IR/CMakeLists.txt @@ -0,0 +1,15 @@ +add_mlir_dialect(IRDL irdl) + +# Add IRDL operations +set(LLVM_TARGET_DEFINITIONS IRDLOps.td) +mlir_tablegen(IRDLOps.h.inc -gen-op-decls) +mlir_tablegen(IRDLOps.cpp.inc -gen-op-defs) +add_public_tablegen_target(MLIRIRDLOpsIncGen) +add_dependencies(mlir-generic-headers MLIRIRDLOpsIncGen) + +# Add IRDL types +set(LLVM_TARGET_DEFINITIONS IRDLTypes.td) +mlir_tablegen(IRDLTypesGen.h.inc -gen-typedef-decls) +mlir_tablegen(IRDLTypesGen.cpp.inc -gen-typedef-defs) +add_public_tablegen_target(MLIRIRDLTypesIncGen) +add_dependencies(mlir-generic-headers MLIRIRDLTypesIncGen) diff --git a/mlir/include/mlir/Dialect/IRDL/IR/IRDL.h b/mlir/include/mlir/Dialect/IRDL/IR/IRDL.h new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/IRDL/IR/IRDL.h @@ -0,0 +1,42 @@ +//===- IRDL.h - IR Definition Language dialect ------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the dialect for the IR Definition Language. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_IRDL_IR_IRDL_H_ +#define MLIR_DIALECT_IRDL_IR_IRDL_H_ + +#include "mlir/Dialect/IRDL/IR/IRDLTraits.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/Interfaces/InferTypeOpInterface.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" +#include + +// Forward declaration. +namespace mlir { +namespace irdl { +class OpDef; +class OpDefAttr; +} // namespace irdl +} // namespace mlir + +//===----------------------------------------------------------------------===// +// IRDL Dialect +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/IRDL/IR/IRDLDialect.h.inc" + +#define GET_TYPEDEF_CLASSES +#include "mlir/Dialect/IRDL/IR/IRDLTypesGen.h.inc" + +#define GET_OP_CLASSES +#include "mlir/Dialect/IRDL/IR/IRDLOps.h.inc" + +#endif // MLIR_DIALECT_IRDL_IR_IRDL_H_ diff --git a/mlir/include/mlir/Dialect/IRDL/IR/IRDL.td b/mlir/include/mlir/Dialect/IRDL/IR/IRDL.td new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/IRDL/IR/IRDL.td @@ -0,0 +1,78 @@ +//===- IRDL.td - IR Definition Language Dialect ------------*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the IR Definition Language dialect. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_IRDL_IR_IRDL +#define MLIR_DIALECT_IRDL_IR_IRDL + +include "mlir/IR/OpBase.td" + +//===----------------------------------------------------------------------===// +// IRDL Dialect +//===----------------------------------------------------------------------===// + +def IRDL_Dialect : Dialect { + let summary = "IR Definition Language Dialect"; + let description = [{ + IRDL is an SSA-based declarative representation of dynamic dialects. + It allows the definition of dialects, operations, attributes, and types, + with a declarative description of their verifiers. IRDL code is meant to + be generated and not written by hand. As such, the design focuses on ease + of generation/analysis instead of ease of writing/reading. + + Users can define a new dialect with `irdl.dialect`, operations with + `irdl.operation`, types with `irdl.type`, and attributes with + `irdl.attribute`. + + An example dialect is shown below: + + ```mlir + irdl.dialect @cmath { + irdl.type @complex { + %0 = irdl.is_type : f32 + %1 = irdl.is_type : f64 + %2 = irdl.any_of(%0, %1) + irdl.parameters(%2) + } + + irdl.operation @mul { + %0 = irdl.is_type : f32 + %1 = irdl.is_type : f64 + %2 = irdl.any_of(%0, %1) + %3 = irdl.parametric_type : "cmath.complex"<%2> + irdl.operands(%3, %3) + irdl.results(%3) + } + } + ``` + + This program defines a `cmath` dialect that defines a `complex` type, and + a `mul` operation. Both express constraints over their parameters using + SSA constraint operations. Informally, one can see those SSA values as + constraint variables that evaluate to a single type at constraint + evaluation. For example, the result of the `irdl.any_of` stored in `%2` + in the `mul` operation will collapse into either `f32` or `f64` for the + entirety of this instance of `mul` constraint evaluation. As such, + both operands and the result of `mul` must be of equal type (and not just + satisfy the same constraint). + + IRDL variables are handle over `mlir::Attribute`. In order to support + manipulating `mlir::Type`, IRDL wraps all types in an `mlir::TypeAttr` + attribute. The rationale of this is to simplify the dialect. + }]; + + let useDefaultTypePrinterParser = 1; + + let name = "irdl"; + let cppNamespace = "::mlir::irdl"; +} + +#endif // MLIR_DIALECT_IRDL_IR_IRDL diff --git a/mlir/include/mlir/Dialect/IRDL/IR/IRDLOps.td b/mlir/include/mlir/Dialect/IRDL/IR/IRDLOps.td new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/IRDL/IR/IRDLOps.td @@ -0,0 +1,358 @@ +//===- IRDLOps.td - IR Definition Language Dialect ---------*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the IRDL dialect ops. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_IRDL_IR_IRDLOPS +#define MLIR_DIALECT_IRDL_IR_IRDLOPS + +include "IRDL.td" +include "IRDLTypes.td" +include "mlir/Interfaces/SideEffectInterfaces.td" +include "mlir/Interfaces/InferTypeOpInterface.td" +include "mlir/IR/SymbolInterfaces.td" + +class IRDL_Op traits = []> + : Op; + +class AtMostOneChildOf : ParamNativeOpTrait<"AtMostOneChildOf", op>; + +//===----------------------------------------------------------------------===// +// Dialect definition +//===----------------------------------------------------------------------===// + +def IRDL_DialectOp : IRDL_Op<"dialect", + [IsolatedFromAbove, NoTerminator, Symbol, SymbolTable]> { + let summary = "Define a new dialect"; + let description = [{ + The `irdl.dialect` operation defines a dialect. All operations, attributes, + and types defined inside its region will be part of the dialect. + + Example: + + ```mlir + irdl.dialect @cmath { + ... + } + ``` + + The above program defines a `cmath` dialect. + }]; + + let arguments = (ins SymbolNameAttr:$sym_name); + let regions = (region SizedRegion<1>:$body); + let assemblyFormat = + "$sym_name attr-dict-with-keyword custom($body)"; + let hasVerifier = 1; +} + +//===----------------------------------------------------------------------===// +// Type and Attribute definition +//===----------------------------------------------------------------------===// + +def IRDL_TypeOp : IRDL_Op<"type", + [HasParent<"DialectOp">, NoTerminator, NoRegionArguments, + AtMostOneChildOf<"ParametersOp">, Symbol]> { + let summary = "Define a new type"; + let description = [{ + `irdl.type` defines a new type belonging to the `irdl.dialect` parent. + + The type parameters can be defined with an `irdl.parameters` operation in + the optional region. + + Example: + + ```mlir + irdl.dialect @cmath { + irdl.type @complex { + %0 = irdl.is i32 + %1 = irdl.is i64 + %2 = irdl.any_of(%0, %1) + irdl.parameters(%2) + } + } + ``` + + The above program defines a type `complex` inside the dialect `cmath`. The + type has a single parameter that should be either `i32` or `i64`. + }]; + + let arguments = (ins SymbolNameAttr:$sym_name); + let regions = (region SizedRegion<1>:$body); + let assemblyFormat = + "$sym_name attr-dict-with-keyword custom($body)"; +} + +def IRDL_AttributeOp : IRDL_Op<"attribute", + [HasParent<"DialectOp">, NoTerminator, NoRegionArguments, + AtMostOneChildOf<"ParametersOp">, Symbol]> { + let summary = "Define a new attribute"; + let description = [{ + `irdl.attribute` defines a new attribute belonging to the `irdl.dialect` + parent. + + The attribute parameters can be defined with an `irdl.parameters` operation + in the optional region. + + Example: + + ```mlir + irdl.dialect @testd { + irdl.attribute @enum_attr { + %0 = irdl.is "foo" + %1 = irdl.is "bar" + %2 = irdl.any_of(%0, %1) + irdl.parameters(%2) + } + } + ``` + + The above program defines an `enum_attr` attribute inside the `testd` + dialect. The attribute has one `StringAttr` parameter that should be + either a `"foo"` or a `"bar"`. + }]; + + let arguments = (ins SymbolNameAttr:$sym_name); + let regions = (region SizedRegion<1>:$body); + let assemblyFormat = + "$sym_name attr-dict-with-keyword custom($body)"; +} + +def IRDL_ParametersOp : IRDL_Op<"parameters", + [ParentOneOf<["AttributeOp", "TypeOp"]>]> { + let summary = + "Define the constraints on parameters of a type/attribute definition"; + let description = [{ + `irdl.parameters` defines the constraints on parameters of a type or + attribute definition. + + Example: + + ```mlir + irdl.dialect @cmath { + irdl.type @complex { + %0 = irdl.is i32 + %1 = irdl.is i64 + %2 = irdl.any_of(%0, %1) + irdl.parameters(%2) + } + } + ``` + + The above program defines a type `complex` inside the dialect `cmath`. The + type has a single parameter that should be either `i32` or `i64`. + }]; + + let arguments = (ins Variadic:$args); + let assemblyFormat = " `(` $args `)` attr-dict "; +} + +//===----------------------------------------------------------------------===// +// IRDL Operation definition +//===----------------------------------------------------------------------===// + +def IRDL_OperationOp : IRDL_Op<"operation", + [HasParent<"DialectOp">, NoTerminator, NoRegionArguments, + AtMostOneChildOf<"OperandsOp, ResultsOp">, Symbol]> { + let summary = "Define a new operation"; + let description = [{ + `irdl.operation` defines a new operation belonging to the `irdl.dialect` + parent. + + Operations can define constraints on their operands and results with the + `irdl.results` and `irdl.operands` operations. If these operations are not + present in the region, the results or operands are expected to be empty. + + Example: + + ```mlir + irdl.dialect @cmath { + + irdl.type @complex { /* ... */ } + + irdl.operation @norm { + %0 = irdl.any + %1 = irdl.parametric @complex<%0> + irdl.results(%0) + irdl.operands(%1) + } + } + ``` + + The above program defines an operation `norm` inside the dialect `cmath`. + The operation expects a single operand of base type `cmath.complex`, and + returns a single result of the element type of the operand. + }]; + + let arguments = (ins SymbolNameAttr:$sym_name); + let regions = (region SizedRegion<1>:$body); + let assemblyFormat = + "$sym_name attr-dict-with-keyword custom($body)"; +} + +def IRDL_OperandsOp : IRDL_Op<"operands", [HasParent<"OperationOp">]> { + let summary = "Define the operands of an operation"; + let description = [{ + `irdl.operands` define the operands of the `irdl.operation` parent operation + definition. + + In the following example, `irdl.operands` defines the operands of the + `norm` operation: + + ```mlir + irdl.dialect @cmath { + + irdl.type @complex { /* ... */ } + + irdl.operation @mul { + %0 = irdl.any + %1 = irdl.parametric @complex<%0> + irdl.results(%1) + irdl.operands(%1, %1) + } + } + ``` + + The `mul` operation will expect two operands of type `cmath.complex`, that + have the same type, and return a result of the same type. + }]; + + let arguments = (ins Variadic:$args); + let assemblyFormat = " `(` $args `)` attr-dict "; +} + +def IRDL_ResultsOp : IRDL_Op<"results", [HasParent<"OperationOp">]> { + let summary = "Define the results of an operation"; + let description = [{ + `irdl.results` define the results of the `irdl.operation` parent operation + definition. + + In the following example, `irdl.results` defines the results of the + `norm` operation: + + ```mlir + irdl.dialect @cmath { + + irdl.type @complex { /* ... */ } + + irdl.operation @get_values { + %0 = irdl.any + %1 = irdl.parametric @complex<%0> + irdl.results(%0, %0) + irdl.operands(%1) + } + } + ``` + + The operation will expect one operand of the `cmath.complex` type, and two + results that have the underlying type of the `cmath.complex`. + }]; + + let arguments = (ins Variadic:$args); + let assemblyFormat = " `(` $args `)` attr-dict "; +} + +//===----------------------------------------------------------------------===// +// IRDL Constraint operations +//===----------------------------------------------------------------------===// + +class IRDL_ConstraintOp traits = []> + : IRDL_Op { +} + +def IRDL_Is : IRDL_ConstraintOp<"is", + [ParentOneOf<["TypeOp", "AttributeOp", "OperationOp"]>, Pure]> { + let summary = "Constraints an attribute/type to be a specific attribute instance"; + let description = [{ + `irdl.is` defines a constraint that only accepts a specific instance of a + type or attribute. + + Example: + + ```mlir + irdl.dialect @cmath { + irdl.type @complex_i32 { + %0 = irdl.is i32 + irdl.parameters(%0) + } + } + ``` + + The above program defines a `complex_i32` type inside the dialect `cmath` + that can only have a `i32` as its parameter. + }]; + + let arguments = (ins AnyAttr:$expected); + let results = (outs IRDL_AttributeType:$output); + let assemblyFormat = " $expected ` ` attr-dict "; +} + +def IRDL_Parametric : IRDL_ConstraintOp<"parametric", + [ParentOneOf<["TypeOp", "AttributeOp", "OperationOp"]>, Pure]> { + let summary = "Constraints an attribute/type base and its parameters"; + let description = [{ + `irdl.parametric` defines a constraint that accepts only a single type + or attribute base. The attribute base is defined by a symbolic reference + to the corresponding definition. It will additionally constraint the + parameters of the type/attribute. + + Example: + + ```mlir + irdl.dialect @cmath { + + irdl.type @complex { /* ... */ } + + irdl.operation @norm { + %0 = irdl.any + %1 = irdl.parametric @complex<%0> + irdl.operands(%1) + irdl.results(%0) + } + } + ``` + + The above program defines an operation `norm` inside the dialect `cmath` that + for any `T` takes a `cmath.complex` with parameter `T` and returns a `T`. + }]; + + let arguments = (ins SymbolRefAttr:$base_type, + Variadic:$args); + let results = (outs IRDL_AttributeType:$output); + let assemblyFormat = " $base_type `<` $args `>` ` ` attr-dict "; +} + +def IRDL_Any : IRDL_ConstraintOp<"any", + [ParentOneOf<["TypeOp", "AttributeOp", "OperationOp"]>]> { + let summary = "Accept any type or attribute"; + let description = [{ + `irdl.any` defines a constraint that accepts any type or attribute. + + Example: + + ```mlir + irdl.dialect @cmath { + irdl.type @complex_flexible { + %0 = irdl.any + irdl.parameters(%0) + } + } + ``` + + The above program defines a type `complex_flexible` inside the dialect + `cmath` that has a single parameter that can be any attribute. + }]; + + let results = (outs IRDL_AttributeType:$output); + let assemblyFormat = " attr-dict "; +} + + +#endif // MLIR_DIALECT_IRDL_IR_IRDLOPS diff --git a/mlir/include/mlir/Dialect/IRDL/IR/IRDLTraits.h b/mlir/include/mlir/Dialect/IRDL/IR/IRDLTraits.h new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/IRDL/IR/IRDLTraits.h @@ -0,0 +1,81 @@ +//===- IRDLTraits.h - IRDL traits definition ---------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the traits used by the IR Definition Language dialect. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_IRDL_IR_IRDLTRAITS_H_ +#define MLIR_DIALECT_IRDL_IR_IRDLTRAITS_H_ + +#include "mlir/IR/OpDefinition.h" +#include "mlir/Support/LogicalResult.h" +#include "llvm/Support/Casting.h" + +namespace mlir { +namespace OpTrait { + +/// Characterize operations that have at most a single operation of certain +/// types in their region. +/// This check is only done on the children that are immediate children of the +/// operation, and does not recurse into the children's regions. +/// This trait expects the Op to satisfy the `OneRegion` trait. +template +class AtMostOneChildOf { +public: + template + class Impl + : public TraitBase::Impl> { + public: + static LogicalResult verifyTrait(Operation *op) { + static_assert( + ConcreteType::template hasTrait<::mlir::OpTrait::OneRegion>(), + "expected operation to have a single region"); + static_assert(sizeof...(ChildOps) > 0, + "expected at least one child operation type"); + + // Contains `true` if the corresponding child op has been seen. + bool satisfiedOps[sizeof...(ChildOps)] = {}; + + for (Operation &child : cast(op).getOps()) { + int childOpIndex = 0; + if (((isa(child) ? false : (++childOpIndex, true)) && ...)) + continue; + + // Check that the operation has not been seen before. + if (satisfiedOps[childOpIndex]) + return op->emitError() + << "failed to verify AtMostOneChildOf trait: the operation " + "contains at least two operations of type " + << child.getName(); + + // Mark the operation as seen. + satisfiedOps[childOpIndex] = true; + } + return success(); + } + + /// Get the unique operation of a specific op that is in the operation + /// region. + template + std::enable_if_t...>::value, + std::optional> + getOp() { + auto ops = + cast(this->getOperation()).template getOps(); + if (ops.empty()) + return {}; + return {*ops.begin()}; + } + }; +}; +} // namespace OpTrait +} // namespace mlir + +#endif // MLIR_DIALECT_IRDL_IR_IRDLTRAITS_H_ diff --git a/mlir/include/mlir/Dialect/IRDL/IR/IRDLTypes.td b/mlir/include/mlir/Dialect/IRDL/IR/IRDLTypes.td new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/IRDL/IR/IRDLTypes.td @@ -0,0 +1,54 @@ +//===- IRDLTypes.td - IRDL Types ---------------------------*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the types IRDL uses. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_IRDL_IR_IRDLTYPES +#define MLIR_DIALECT_IRDL_IR_IRDLTYPES + +include "mlir/IR/AttrTypeBase.td" +include "IRDL.td" + +class IRDL_Type traits = []> + : TypeDef { + let mnemonic = typeMnemonic; +} + +def IRDL_AttributeType : IRDL_Type<"Attribute", "attribute"> { + let summary = "IRDL handle to an `mlir::Attribute`"; + let description = [{ + This type represents a handle to an instance of an `mlir::Attribute`, + so it can be used in an IRDL operation, type, or attribute definition. + This type can also represent a handle to an instance of an `mlir::Type`, + by wrapping it in a `mlir::TypeAttr`. + + Example: + + ```mlir + irdl.dialect cmath { + + irdl.type @complex { /* ... */ } + + irdl.operation @norm { + %0 = irdl.any + %1 = irdl.parametric @complex<%0> + irdl.operands(%1) + irdl.results(%0) + } + } + ``` + + Here, `%0` and `%1` are both of type `!irdl.attribute`. Note that in + particular, `%1` will be a handle to a `mlir::TypeAttr` wrapping an + instance of a `cmath.complex` type. + }]; +} + +#endif // MLIR_DIALECT_IRDL_IR_IRDLTYPES diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h --- a/mlir/include/mlir/InitAllDialects.h +++ b/mlir/include/mlir/InitAllDialects.h @@ -33,6 +33,7 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/GPU/IR/GPUDialect.h" #include "mlir/Dialect/GPU/TransformOps/GPUTransformOps.h" +#include "mlir/Dialect/IRDL/IR/IRDL.h" #include "mlir/Dialect/Index/IR/IndexDialect.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/LLVMIR/NVVMDialect.h" @@ -93,6 +94,7 @@ func::FuncDialect, gpu::GPUDialect, index::IndexDialect, + irdl::IRDLDialect, LLVM::LLVMDialect, linalg::LinalgDialect, math::MathDialect, diff --git a/mlir/lib/Dialect/CMakeLists.txt b/mlir/lib/Dialect/CMakeLists.txt --- a/mlir/lib/Dialect/CMakeLists.txt +++ b/mlir/lib/Dialect/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(Func) add_subdirectory(GPU) add_subdirectory(Index) +add_subdirectory(IRDL) add_subdirectory(Linalg) add_subdirectory(LLVMIR) add_subdirectory(Math) diff --git a/mlir/lib/Dialect/IRDL/CMakeLists.txt b/mlir/lib/Dialect/IRDL/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/mlir/lib/Dialect/IRDL/CMakeLists.txt @@ -0,0 +1,11 @@ +add_mlir_dialect_library(MLIRIRDL + IR/IRDL.cpp + + DEPENDS + MLIRIRDLIncGen + MLIRIRDLOpsIncGen + MLIRIRDLTypesIncGen + + LINK_LIBS PUBLIC + MLIRIR + ) diff --git a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp new file mode 100644 --- /dev/null +++ b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp @@ -0,0 +1,78 @@ +//===- IRDL.cpp - IRDL dialect ----------------------------------*- C++ -*-===// +// +// This file is licensed 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 +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/IRDL/IR/IRDL.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/DialectImplementation.h" +#include "mlir/IR/ExtensibleDialect.h" +#include "mlir/IR/OpDefinition.h" +#include "mlir/IR/OpImplementation.h" +#include "mlir/Support/LogicalResult.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/TypeSwitch.h" +#include "llvm/IR/Metadata.h" +#include "llvm/Support/Casting.h" + +using namespace mlir; +using namespace mlir::irdl; + +//===----------------------------------------------------------------------===// +// IRDL dialect. +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/IRDL/IR/IRDL.cpp.inc" + +#include "mlir/Dialect/IRDL/IR/IRDLDialect.cpp.inc" + +void IRDLDialect::initialize() { + addOperations< +#define GET_OP_LIST +#include "mlir/Dialect/IRDL/IR/IRDLOps.cpp.inc" + >(); + addTypes< +#define GET_TYPEDEF_LIST +#include "mlir/Dialect/IRDL/IR/IRDLTypesGen.cpp.inc" + >(); +} + +//===----------------------------------------------------------------------===// +// Parsing/Printing +//===----------------------------------------------------------------------===// + +/// Parse a region, and add a single block if the region is empty. +/// If no region is parsed, create a new region with a single empty block. +static ParseResult parseSingleBlockRegion(OpAsmParser &p, Region ®ion) { + auto regionParseRes = p.parseOptionalRegion(region); + if (regionParseRes.has_value() && failed(regionParseRes.value())) + return failure(); + + // If the region is empty, add a single empty block. + if (region.empty()) + region.push_back(new Block()); + + return success(); +} + +static void printSingleBlockRegion(OpAsmPrinter &p, Operation *op, + Region ®ion) { + if (!region.getBlocks().front().empty()) + p.printRegion(region); +} + +LogicalResult DialectOp::verify() { + if (!Dialect::isValidNamespace(getName())) + return emitOpError("invalid dialect name"); + return success(); +} + +#define GET_TYPEDEF_CLASSES +#include "mlir/Dialect/IRDL/IR/IRDLTypesGen.cpp.inc" + +#define GET_OP_CLASSES +#include "mlir/Dialect/IRDL/IR/IRDLOps.cpp.inc" diff --git a/mlir/test/Dialect/IRDL/cmath.irdl.mlir b/mlir/test/Dialect/IRDL/cmath.irdl.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/Dialect/IRDL/cmath.irdl.mlir @@ -0,0 +1,43 @@ +// RUN: mlir-opt %s | mlir-opt | FileCheck %s + +module { + // CHECK-LABEL: irdl.dialect @cmath { + irdl.dialect @cmath { + + // CHECK: irdl.type @complex { + // CHECK: %[[v0:[^ ]*]] = irdl.is f32 + // CHECK: irdl.parameters(%[[v0]]) + // CHECK: } + irdl.type @complex { + %0 = irdl.is f32 + irdl.parameters(%0) + } + + // CHECK: irdl.operation @norm { + // CHECK: %[[v0:[^ ]*]] = irdl.any + // CHECK: %[[v1:[^ ]*]] = irdl.parametric @complex<%[[v0]]> + // CHECK: irdl.operands(%[[v1]]) + // CHECK: irdl.results(%[[v0]]) + // CHECK: } + irdl.operation @norm { + %0 = irdl.any + %1 = irdl.parametric @complex<%0> + irdl.operands(%1) + irdl.results(%0) + } + + // CHECK: irdl.operation @mul { + // CHECK: %[[v0:[^ ]*]] = irdl.is f32 + // CHECK: %[[v3:[^ ]*]] = irdl.parametric @complex<%[[v0]]> + // CHECK: irdl.operands(%[[v3]], %[[v3]]) + // CHECK: irdl.results(%[[v3]]) + // CHECK: } + irdl.operation @mul { + %0 = irdl.is f32 + %3 = irdl.parametric @complex<%0> + irdl.operands(%3, %3) + irdl.results(%3) + } + + } +} diff --git a/mlir/test/Dialect/IRDL/testd.irdl.mlir b/mlir/test/Dialect/IRDL/testd.irdl.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/Dialect/IRDL/testd.irdl.mlir @@ -0,0 +1,71 @@ +// RUN: mlir-opt %s | mlir-opt | FileCheck %s + +// CHECK: irdl.dialect @testd { +irdl.dialect @testd { + // CHECK: irdl.type @parametric { + // CHECK: %[[v0:[^ ]*]] = irdl.any + // CHECK: irdl.parameters(%[[v0]]) + // CHECK: } + irdl.type @parametric { + %0 = irdl.any + irdl.parameters(%0) + } + + // CHECK: irdl.type @attr_in_type_out { + // CHECK: %[[v0:[^ ]*]] = irdl.any + // CHECK: irdl.parameters(%[[v0]]) + // CHECK: } + irdl.type @attr_in_type_out { + %0 = irdl.any + irdl.parameters(%0) + } + + // CHECK: irdl.operation @eq { + // CHECK: %[[v0:[^ ]*]] = irdl.is i32 + // CHECK: irdl.results(%[[v0]]) + // CHECK: } + irdl.operation @eq { + %0 = irdl.is i32 + irdl.results(%0) + } + + // CHECK: irdl.operation @any { + // CHECK: %[[v0:[^ ]*]] = irdl.any + // CHECK: irdl.results(%[[v0]]) + // CHECK: } + irdl.operation @any { + %0 = irdl.any + irdl.results(%0) + } + + // CHECK: irdl.operation @dynbase { + // CHECK: %[[v0:[^ ]*]] = irdl.any + // CHECK: %[[v1:[^ ]*]] = irdl.parametric @parametric<%[[v0]]> + // CHECK: irdl.results(%[[v1]]) + // CHECK: } + irdl.operation @dynbase { + %0 = irdl.any + %1 = irdl.parametric @parametric<%0> + irdl.results(%1) + } + + // CHECK: irdl.operation @dynparams { + // CHECK: %[[v0:[^ ]*]] = irdl.is i32 + // CHECK: %[[v3:[^ ]*]] = irdl.parametric @parametric<%[[v0]]> + // CHECK: irdl.results(%[[v3]]) + // CHECK: } + irdl.operation @dynparams { + %0 = irdl.is i32 + %3 = irdl.parametric @parametric<%0> + irdl.results(%3) + } + + // CHECK: irdl.operation @constraint_vars { + // CHECK: %[[v0:[^ ]*]] = irdl.any + // CHECK: irdl.results(%[[v0]], %[[v0]]) + // CHECK: } + irdl.operation @constraint_vars { + %0 = irdl.any + irdl.results(%0, %0) + } +} diff --git a/mlir/test/mlir-opt/commandline.mlir b/mlir/test/mlir-opt/commandline.mlir --- a/mlir/test/mlir-opt/commandline.mlir +++ b/mlir/test/mlir-opt/commandline.mlir @@ -17,6 +17,7 @@ // CHECK-SAME: func // CHECK-SAME: gpu // CHECK-SAME: index +// CHECK-SAME: irdl // CHECK-SAME: linalg // CHECK-SAME: llvm // CHECK-SAME: math