Add spv.Undef op to support OpUndef instruction in SPIR-V.
authorMahesh Ravishankar <ravishankarm@google.com>
Fri, 4 Oct 2019 22:59:54 +0000 (15:59 -0700)
committerA. Unique TensorFlower <gardener@tensorflow.org>
Fri, 4 Oct 2019 23:00:22 +0000 (16:00 -0700)
Adding support for OpUndef instruction. Updating the dialect
generation script to fix a few bugs in the instruction spec
generation.

PiperOrigin-RevId: 272975685

mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
mlir/include/mlir/Dialect/SPIRV/SPIRVOps.td
mlir/lib/Dialect/SPIRV/SPIRVOps.cpp
mlir/test/Dialect/SPIRV/Serialization/undef.mlir [new file with mode: 0644]
mlir/test/Dialect/SPIRV/ops.mlir
mlir/utils/spirv/gen_spirv_dialect.py

index 3893361..a24cdf9 100644 (file)
@@ -73,6 +73,7 @@ class SPV_OpCode<string name, int val> {
 // Begin opcode section. Generated from SPIR-V spec; DO NOT MODIFY!
 
 def SPV_OC_OpNop                    : I32EnumAttrCase<"OpNop", 0>;
+def SPV_OC_OpUndef                  : I32EnumAttrCase<"OpUndef", 1>;
 def SPV_OC_OpSourceContinued        : I32EnumAttrCase<"OpSourceContinued", 2>;
 def SPV_OC_OpSource                 : I32EnumAttrCase<"OpSource", 3>;
 def SPV_OC_OpSourceExtension        : I32EnumAttrCase<"OpSourceExtension", 4>;
@@ -173,7 +174,7 @@ def SPV_OC_OpModuleProcessed        : I32EnumAttrCase<"OpModuleProcessed", 330>;
 
 def SPV_OpcodeAttr :
     I32EnumAttr<"Opcode", "valid SPIR-V instructions", [
-      SPV_OC_OpNop, SPV_OC_OpSourceContinued, SPV_OC_OpSource,
+      SPV_OC_OpNop, SPV_OC_OpUndef, SPV_OC_OpSourceContinued, SPV_OC_OpSource,
       SPV_OC_OpSourceExtension, SPV_OC_OpName, SPV_OC_OpMemberName, SPV_OC_OpString,
       SPV_OC_OpExtension, SPV_OC_OpExtInstImport, SPV_OC_OpExtInst,
       SPV_OC_OpMemoryModel, SPV_OC_OpEntryPoint, SPV_OC_OpExecutionMode,
index 860a5c2..178d358 100644 (file)
@@ -485,6 +485,41 @@ def SPV_StoreOp : SPV_Op<"Store", []> {
 
 // -----
 
+def SPV_UndefOp : SPV_Op<"Undef", []> {
+  let summary = "Make an intermediate object whose value is undefined.";
+
+  let description = [{
+    Result Type is the type of object to make.
+
+    Each consumption of Result <id> yields an arbitrary, possibly different
+    bit pattern or abstract value resulting in possibly different concrete,
+    abstract, or opaque values.
+
+    ### Custom assembly form
+
+    ``` {.ebnf}
+    undef-op ::= `spv.Undef` `:` sprirv-type
+    ```
+
+    For example:
+
+    ```
+    %0 = spv.Undef : f32
+    %1 = spv.Undef : !spv.struct<!spv.array<4 x vector<4xi32>>>
+    ```
+  }];
+
+  let arguments = (ins);
+
+  let results = (outs
+    SPV_Type:$result
+  );
+
+  let verifier = [{ return success(); }];
+}
+
+// -----
+
 def SPV_VariableOp : SPV_Op<"Variable", []> {
   let summary = [{
     Allocate an object in memory, resulting in a pointer to it, which can be
index 2ff3a6d..800771c 100644 (file)
@@ -2033,6 +2033,23 @@ static LogicalResult verify(spirv::StoreOp storeOp) {
 }
 
 //===----------------------------------------------------------------------===//
+// spv.Undef
+//===----------------------------------------------------------------------===//
+
+static ParseResult parseUndefOp(OpAsmParser &parser, OperationState &state) {
+  Type type;
+  if (parser.parseColonType(type)) {
+    return failure();
+  }
+  state.addTypes(type);
+  return success();
+}
+
+static void print(spirv::UndefOp undefOp, OpAsmPrinter &printer) {
+  printer << spirv::UndefOp::getOperationName() << " : " << undefOp.getType();
+}
+
+//===----------------------------------------------------------------------===//
 // spv.Variable
 //===----------------------------------------------------------------------===//
 
diff --git a/mlir/test/Dialect/SPIRV/Serialization/undef.mlir b/mlir/test/Dialect/SPIRV/Serialization/undef.mlir
new file mode 100644 (file)
index 0000000..7c2ccdb
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: mlir-translate -test-spirv-roundtrip %s | FileCheck %s
+
+spv.module "Logical" "GLSL450" {
+  func @foo() -> () {
+    // CHECK: {{%.*}} = spv.Undef : f32
+    %0 = spv.Undef : f32
+    // CHECK: {{%.*}} = spv.Undef : vector<4xi32>
+    %1 = spv.Undef : vector<4xi32>
+    // CHECK: {{%.*}} = spv.Undef : !spv.array<4 x !spv.array<4 x i32>>
+    %2 = spv.Undef : !spv.array<4x!spv.array<4xi32>>
+    // CHECK: {{%.*}} = spv.Undef : !spv.ptr<!spv.struct<f32>, StorageBuffer>
+    %3 = spv.Undef : !spv.ptr<!spv.struct<f32>, StorageBuffer>
+    spv.Return
+  }
+}
\ No newline at end of file
index d24015a..63c034f 100644 (file)
@@ -968,6 +968,35 @@ spv.module "Logical" "GLSL450" {
 // -----
 
 //===----------------------------------------------------------------------===//
+// spv.Undef
+//===----------------------------------------------------------------------===//
+
+func @undef() -> () {
+  %0 = spv.Undef : f32
+  %1 = spv.Undef : vector<4xf32>
+  spv.Return
+}
+
+// -----
+
+func @undef() -> () {
+  // expected-error @+2{{expected non-function type}}
+  %0 = spv.Undef :
+  spv.Return
+}
+
+// -----
+
+func @undef() -> () {
+  // expected-error @+2{{expected ':'}}
+  %0 = spv.Undef
+  spv.Return
+}
+
+// -----
+
+
+//===----------------------------------------------------------------------===//
 // spv.Variable
 //===----------------------------------------------------------------------===//
 
index 1e317e0..59d3831 100755 (executable)
@@ -385,7 +385,7 @@ def get_description(text, assembly):
   Returns:
     - A string that corresponds to the description of the Tablegen op.
   """
-  fmt_str = ('{text}\n\n    ### Custom assembly ' 'form\n{assembly}}}];\n')
+  fmt_str = ('{text}\n\n    ### Custom assembly ' 'form\n{assembly}\n  ')
   return fmt_str.format(
       text=text, assembly=assembly)
 
@@ -466,8 +466,8 @@ def get_op_definition(instruction, doc, existing_info):
                '    ```\n\n'\
                '    For example:\n\n'\
                '    ```\n'\
-               '    [TODO]\n'\
-               '    ```\n  '
+               '    [TODO]\n' \
+               '    ```'
     description = get_description(text, assembly)
 
   return fmt_str.format(