mlir_tablegen(SPIRVOps.h.inc -gen-op-decls)
mlir_tablegen(SPIRVOps.cpp.inc -gen-op-defs)
add_public_tablegen_target(MLIRSPIRVOpsIncGen)
+
+set(LLVM_TARGET_DEFINITIONS SPIRVStructureOps.td)
+mlir_tablegen(SPIRVStructureOps.h.inc -gen-op-decls)
+mlir_tablegen(SPIRVStructureOps.cpp.inc -gen-op-defs)
+add_public_tablegen_target(MLIRSPIRVStructureOpsIncGen)
--- /dev/null
+//===-- SPIRVOps.td - MLIR SPIR-V Op Definitions Spec ------*- tablegen -*-===//
+//
+// Copyright 2019 The MLIR Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// =============================================================================
+//
+// This is the base file for SPIR-V operation definition specification.
+// This file defines the SPIR-V dialect, common SPIR-V types, and utilities
+// for facilitating defining SPIR-V ops.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef SPIRV_BASE
+#else
+#define SPIRV_BASE
+
+#ifdef OP_BASE
+#else
+include "mlir/IR/OpBase.td"
+#endif // OP_BASE
+
+//===----------------------------------------------------------------------===//
+// SPIR-V dialect definitions
+//===----------------------------------------------------------------------===//
+
+def SPV_Dialect : Dialect {
+ let name = "spv";
+
+ let description = [{
+ The SPIR-V dialect in MLIR.
+
+ SPIR-V is the Khronos Group's binary intermediate language for representing
+ graphical-shader stages and compute kernels for multiple Khronos APIs,
+ including OpenCL, OpenGL, and Vulkan.
+ See https://www.khronos.org/registry/spir-v for more details.
+
+ This dialect aims to be a simple proxy for the SPIR-V binary format to
+ enable straightforward and lightweight conversion from/to the binary
+ format. Ops in this dialect should stay at the same semantic level and
+ try to be a mechanical mapping to the corresponding SPIR-V instructions;
+ but they may deviate representationally to allow using MLIR mechanisms.
+ As a convention, if such deviation happens, the op name follows "snake_case"
+ style; otherwise, the op name just follows the SPIR-V mnemonic (by removing
+ the leading `Op` prefix) to use "CamelCase" style.
+ }];
+
+ let cppNamespace = "spirv";
+}
+
+//===----------------------------------------------------------------------===//
+// SPIR-V type definitions
+//===----------------------------------------------------------------------===//
+
+class SPV_ScalarOrVectorOf<Type type> :
+ Type<Or<[type.predicate, VectorOf<[type]>.predicate]>,
+ "scalar/vector of " # type.description>;
+
+def SPV_AM_Logical : EnumAttrCase<"Logical">;
+def SPV_AM_Pysical32 : EnumAttrCase<"Pysical32">;
+def SPV_AM_Pysical64 : EnumAttrCase<"Pysical64">;
+
+def SPV_AddressingModelAttr :
+ EnumAttr<"AddressingModel", "SPIR-V addressing model", [
+ SPV_AM_Logical, SPV_AM_Pysical32, SPV_AM_Pysical64
+ ]>;
+
+def SPV_MM_Simple : EnumAttrCase<"Simple">;
+def SPV_MM_GLSL450 : EnumAttrCase<"GLSL450">;
+def SPV_MM_OpenCL : EnumAttrCase<"OpenCL">;
+def SPV_MM_VulkanKHR : EnumAttrCase<"VulkanKHR">;
+
+def SPV_MemoryModelAttr :
+ EnumAttr<"MemoryModel", "SPIR-V memory model", [
+ SPV_MM_Simple, SPV_MM_GLSL450, SPV_MM_OpenCL, SPV_MM_VulkanKHR
+ ]>;
+
+//===----------------------------------------------------------------------===//
+// SPIR-V op definitions
+//===----------------------------------------------------------------------===//
+
+// Base class for all SPIR-V ops.
+class SPV_Op<string mnemonic, list<OpTrait> traits = []> :
+ Op<SPV_Dialect, mnemonic, traits>;
+
+#endif // SPIRV_BASE
#define GET_OP_CLASSES
#include "mlir/SPIRV/SPIRVOps.h.inc"
+#define GET_OP_CLASSES
+#include "mlir/SPIRV/SPIRVStructureOps.h.inc"
} // end namespace spirv
} // end namespace mlir
// limitations under the License.
// =============================================================================
//
-// This is the operation definition specification file for SPIR-V operations.
+// This is the main operation definition specification file for SPIR-V
+// operations.
//
//===----------------------------------------------------------------------===//
#else
#define SPIRV_OPS
-#ifdef OP_BASE
+#ifdef SPIRV_BASE
#else
-include "mlir/IR/OpBase.td"
-#endif // OP_BASE
-
-//===----------------------------------------------------------------------===//
-// SPIR-V dialect definitions
-//===----------------------------------------------------------------------===//
-
-def SPV_Dialect : Dialect {
- let name = "spv";
-
- let description = [{
- The SPIR-V dialect in MLIR.
-
- SPIR-V is the Khronos Group's binary intermediate language for representing
- graphical-shader stages and compute kernels for multiple Khronos APIs,
- including OpenCL, OpenGL, and Vulkan.
- See https://www.khronos.org/registry/spir-v for more details.
-
- This dialect aims to be a simple proxy for the SPIR-V binary format to
- enable straightforward and lightweight conversion from/to the binary
- format. Ops in this dialect should stay at the same semantic level and
- try to be a mechanical mapping to the corresponding SPIR-V instructions;
- but they may deviate representationally to allow using MLIR mechanisms.
- }];
-
- let cppNamespace = "spirv";
-}
-
-//===----------------------------------------------------------------------===//
-// SPIR-V type definitions
-//===----------------------------------------------------------------------===//
-
-class SPV_ScalarOrVectorOf<Type type> :
- Type<Or<[type.predicate, VectorOf<[type]>.predicate]>,
- "scalar/vector of " # type.description>;
-
-//===----------------------------------------------------------------------===//
-// SPIR-V op definitions
-//===----------------------------------------------------------------------===//
-
-// Base class for all SPIR-V ops.
-class SPV_Op<string mnemonic, list<OpTrait> traits = []> :
- Op<SPV_Dialect, mnemonic, traits>;
+include "mlir/SPIRV/SPIRVBase.td"
+#endif // SPIRV_BASE
def SPV_FMulOp : SPV_Op<"FMul", [NoSideEffect, SameOperandsAndResultType]> {
let summary = "Floating-point multiplication of Operand 1 and Operand 2";
--- /dev/null
+//===-- SPIRVOps.td - MLIR SPIR-V Op Definitions Spec ------*- tablegen -*-===//
+//
+// Copyright 2019 The MLIR Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// =============================================================================
+//
+// This file contains ops for defining the SPIR-V structure: module, function,
+// and module-level operations. The representational form of these ops deviate
+// from the SPIR-V binary format in order to utilize MLIR mechanisms.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef SPIRV_STRUCTURE_OPS
+#else
+#define SPIRV_STRUCTURE_OPS
+
+#ifdef SPIRV_BASE
+#else
+include "mlir/SPIRV/SPIRVBase.td"
+#endif // SPIRV_BASE
+
+def SPV_ModuleOp : SPV_Op<"module", []> {
+ let summary = "The top-level op that defines a SPIR-V module";
+
+ let description = [{
+ This op defines a SPIR-V module using a MLIR region. The region contains
+ one block. Module-level operations, including functions definitions,
+ are all placed in this block.
+
+ Using an op with a region to define a SPIR-V module enables "embedding"
+ SPIR-V modules in other dialects in a clean manner: this op guarantees
+ the validaty and serializability of a SPIR-V module and thus serves as
+ a clear-cut boundary.
+
+ Regularity is one of the design goals of SPIR-V. All concepts are
+ represented as SPIR-V instructions, including declaring extensions and
+ capabilities, defining types and constants, defining functions, attaching
+ additional properties to computation results, etc. This way favors driver
+ consumption but not necessarily compiler transformations. The purpose of
+ the SPIR-V dialect is to serve as the proxy of the binary format and to
+ facilitate transformations. So we adjust how certain module-level SPIR-V
+ instructions are represented in the SPIR-V dialect. Notably,
+
+ * Requirements for capabilities, extensions, extended instruction sets,
+ addressing model, and memory model is conveyed using op attributes.
+ This is considered better because these information are for the
+ exexcution environment. It's eaiser to probe them if on the module op
+ itself.
+
+ This op takes no operands and generates no results. This op should not
+ implicitly capture values from the enclosing environment.
+ }];
+
+ let arguments = (ins
+ OptionalAttr<StrArrayAttr>:$capabilities,
+ OptionalAttr<StrArrayAttr>:$extensions,
+ OptionalAttr<StrArrayAttr>:$extended_instruction_sets,
+ SPV_AddressingModelAttr:$addressing_model,
+ SPV_MemoryModelAttr:$memory_model
+ );
+
+ let results = (outs);
+
+ let numRegions = 1;
+
+ // Custom parser and printer implemented by static functions in SPVOps.cpp
+ let parser = [{ return parseModule(parser, result); }];
+ let printer = [{ printModule(getOperation(), p); }];
+}
+
+#endif // SPIRV_STRUCTURE_OPS
${MLIR_MAIN_INCLUDE_DIR}/mlir/SPIRV
)
-add_dependencies(MLIRSPIRV MLIRSPIRVOpsIncGen)
+add_dependencies(MLIRSPIRV MLIRSPIRVOpsIncGen MLIRSPIRVStructureOpsIncGen)
target_link_libraries(MLIRSPIRV MLIRIR MLIRSupport)
#define GET_OP_LIST
#include "mlir/SPIRV/SPIRVOps.cpp.inc"
>();
+ addOperations<
+#define GET_OP_LIST
+#include "mlir/SPIRV/SPIRVStructureOps.cpp.inc"
+ >();
// Allow unknown operations because SPIR-V is extensible.
allowUnknownOperations();
#include "mlir/SPIRV/SPIRVOps.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/StandardTypes.h"
+using namespace mlir;
+
+//===----------------------------------------------------------------------===//
+// spv.module
+//===----------------------------------------------------------------------===//
+
+static ParseResult parseModule(OpAsmParser *parser, OperationState *state) {
+ Region *body = state->addRegion();
+
+ if (parser->parseRegion(*body, /*arguments=*/{}, /*argTypes=*/{}) ||
+ parser->parseKeyword("attributes") ||
+ parser->parseOptionalAttributeDict(state->attributes))
+ return failure();
+
+ return success();
+}
+
+static ParseResult printModule(Operation *op, OpAsmPrinter *printer) {
+ *printer << op->getName();
+ printer->printRegion(op->getRegion(0), /*printEntryBlockArgs=*/false,
+ /*printBlockTerminators=*/false);
+ *printer << " attributes";
+ printer->printOptionalAttrDict(op->getAttrs(),
+ /*elidedAttrs=*/{});
+ return success();
+}
+
namespace mlir {
namespace spirv {
#define GET_OP_CLASSES
#include "mlir/SPIRV/SPIRVOps.cpp.inc"
+#define GET_OP_CLASSES
+#include "mlir/SPIRV/SPIRVStructureOps.cpp.inc"
} // namespace spirv
} // namespace mlir
--- /dev/null
+// RUN: mlir-opt -split-input-file -verify %s | FileCheck %s
+
+// TODO(antiagainst): Remove the wrapping functions once MLIR is moved to
+// be generally region-based.
+
+//===----------------------------------------------------------------------===//
+// spv.module
+//===----------------------------------------------------------------------===//
+
+func @module_without_cap_ext() -> () {
+ // CHECK: spv.module
+ spv.module { } attributes {
+ addressing_model: "Logical",
+ memory_model: "VulkanKHR"
+ }
+ return
+}
+
+func @module_with_cap_ext() -> () {
+ // CHECK: spv.module
+ spv.module { } attributes {
+ capability: ["Shader"],
+ extension: ["SPV_KHR_16bit_storage"],
+ addressing_model: "Logical",
+ memory_model: "VulkanKHR"
+ }
+ return
+}
+
+// -----
+
+func @missing_addressing_model() -> () {
+ // expected-error@+1 {{requires attribute 'addressing_model'}}
+ spv.module { } attributes {}
+ return
+}
+
+// -----
+
+func @wrong_addressing_model() -> () {
+ // expected-error@+1 {{attribute 'addressing_model' failed to satisfy constraint}}
+ spv.module { } attributes {addressing_model: "Physical", memory_model: "VulkanHKR"}
+ return
+}
+
+// -----
+
+func @missing_memory_model() -> () {
+ // expected-error@+1 {{requires attribute 'memory_model'}}
+ spv.module { } attributes {addressing_model: "Logical"}
+ return
+}