[llvm-branch-commits] [mlir] 2f7ec77 - [mlir][spirv] NFC: place ops in the proper file for their categories

Lei Zhang via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jan 12 07:32:52 PST 2021


Author: Lei Zhang
Date: 2021-01-12T10:19:37-05:00
New Revision: 2f7ec77e3cdb9d874e0b6a73d3d7a6fe02c0125d

URL: https://github.com/llvm/llvm-project/commit/2f7ec77e3cdb9d874e0b6a73d3d7a6fe02c0125d
DIFF: https://github.com/llvm/llvm-project/commit/2f7ec77e3cdb9d874e0b6a73d3d7a6fe02c0125d.diff

LOG: [mlir][spirv] NFC: place ops in the proper file for their categories

This commit moves dangling ops in the main ops.td file to the proper
file matching their categories. This makes ops.td as purely including
all category files.

Differential Revision: https://reviews.llvm.org/D94413

Added: 
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBarrierOps.td
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVMemoryOps.td
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVMiscOps.td
    mlir/test/Dialect/SPIRV/IR/barrier-ops.mlir
    mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
    mlir/test/Dialect/SPIRV/IR/memory-ops.mlir
    mlir/test/Dialect/SPIRV/IR/misc-ops.mlir
    mlir/test/Target/SPIRV/barrier-ops.mlir

Modified: 
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.td
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td
    mlir/test/Dialect/SPIRV/IR/bit-ops.mlir
    mlir/test/Dialect/SPIRV/IR/group-ops.mlir
    mlir/test/Dialect/SPIRV/IR/logical-ops.mlir
    mlir/test/Dialect/SPIRV/IR/structure-ops.mlir

Removed: 
    mlir/test/Dialect/SPIRV/IR/ops.mlir
    mlir/test/Target/SPIRV/barrier.mlir


################################################################################
diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBarrierOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBarrierOps.td
new file mode 100644
index 000000000000..98a0c300e69f
--- /dev/null
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBarrierOps.td
@@ -0,0 +1,141 @@
+//===-- SPIRVBarrierOps.td - MLIR SPIR-V Barrier Ops -------*- 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 contains barrier ops for the SPIR-V dialect. It corresponds
+// to "3.32.20. Barrrier Instructions" of the SPIR-V spec.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_SPIRV_IR_BARRIER_OPS
+#define MLIR_DIALECT_SPIRV_IR_BARRIER_OPS
+
+include "mlir/Dialect/SPIRV/IR/SPIRVBase.td"
+
+// -----
+
+def SPV_ControlBarrierOp : SPV_Op<"ControlBarrier", []> {
+  let summary = [{
+    Wait for other invocations of this module to reach the current point of
+    execution.
+  }];
+
+  let description = [{
+    All invocations of this module within Execution scope must reach this
+    point of execution before any invocation will proceed beyond it.
+
+    When Execution is Workgroup or larger, behavior is undefined if this
+    instruction is used in control flow that is non-uniform within
+    Execution. When Execution is Subgroup or Invocation, the behavior of
+    this instruction in non-uniform control flow is defined by the client
+    API.
+
+    If Semantics is not None, this instruction also serves as an
+    OpMemoryBarrier instruction, and must also perform and adhere to the
+    description and semantics of an OpMemoryBarrier instruction with the
+    same Memory and Semantics operands.  This allows atomically specifying
+    both a control barrier and a memory barrier (that is, without needing
+    two instructions). If Semantics is None, Memory is ignored.
+
+    Before version 1.3, it is only valid to use this instruction with
+    TessellationControl, GLCompute, or Kernel execution models. There is no
+    such restriction starting with version 1.3.
+
+    When used with the TessellationControl execution model, it also
+    implicitly synchronizes the Output Storage Class:  Writes to Output
+    variables performed by any invocation executed prior to a
+    OpControlBarrier will be visible to any other invocation after return
+    from that OpControlBarrier.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    scope ::= `"CrossDevice"` | `"Device"` | `"Workgroup"` | ...
+
+    memory-semantics ::= `"None"` | `"Acquire"` | "Release"` | ...
+
+    control-barrier-op ::= `spv.ControlBarrier` scope, scope, memory-semantics
+    ```
+
+    #### Example:
+
+    ```mlir
+    spv.ControlBarrier "Workgroup", "Device", "Acquire|UniformMemory"
+
+    ```
+  }];
+
+  let arguments = (ins
+    SPV_ScopeAttr:$execution_scope,
+    SPV_ScopeAttr:$memory_scope,
+    SPV_MemorySemanticsAttr:$memory_semantics
+  );
+
+  let results = (outs);
+
+  let verifier = [{ return verifyMemorySemantics(*this); }];
+
+  let autogenSerialization = 0;
+
+  let assemblyFormat = [{
+    $execution_scope `,` $memory_scope `,` $memory_semantics attr-dict
+  }];
+}
+
+// -----
+
+def SPV_MemoryBarrierOp : SPV_Op<"MemoryBarrier", []> {
+  let summary = "Control the order that memory accesses are observed.";
+
+  let description = [{
+    Ensures that memory accesses issued before this instruction will be
+    observed before memory accesses issued after this instruction. This
+    control is ensured only for memory accesses issued by this invocation
+    and observed by another invocation executing within Memory scope. If the
+    Vulkan memory model is declared, this ordering only applies to memory
+    accesses that use the NonPrivatePointer memory operand or
+    NonPrivateTexel image operand.
+
+    Semantics declares what kind of memory is being controlled and what kind
+    of control to apply.
+
+    To execute both a memory barrier and a control barrier, see
+    OpControlBarrier.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    scope ::= `"CrossDevice"` | `"Device"` | `"Workgroup"` | ...
+
+    memory-semantics ::= `"None"` | `"Acquire"` | `"Release"` | ...
+
+    memory-barrier-op ::= `spv.MemoryBarrier` scope, memory-semantics
+    ```
+
+    #### Example:
+
+    ```mlir
+    spv.MemoryBarrier "Device", "Acquire|UniformMemory"
+
+    ```
+  }];
+
+  let arguments = (ins
+    SPV_ScopeAttr:$memory_scope,
+    SPV_MemorySemanticsAttr:$memory_semantics
+  );
+
+  let results = (outs);
+
+  let verifier = [{ return verifyMemorySemantics(*this); }];
+
+  let autogenSerialization = 0;
+
+  let assemblyFormat = "$memory_scope `,` $memory_semantics attr-dict";
+}
+
+#endif // MLIR_DIALECT_SPIRV_IR_BARRIER_OPS

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVMemoryOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVMemoryOps.td
new file mode 100644
index 000000000000..ef296668cbc3
--- /dev/null
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVMemoryOps.td
@@ -0,0 +1,296 @@
+//===-- SPIRVMemoryOps.td - MLIR SPIR-V Memory Ops ---------*- 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 contains memory ops for the SPIR-V dialect. It corresponds
+// to "3.32.8. Memory Instructions" of the SPIR-V spec.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_SPIRV_IR_MEMORY_OPS
+#define MLIR_DIALECT_SPIRV_IR_MEMORY_OPS
+
+include "mlir/Dialect/SPIRV/IR/SPIRVBase.td"
+
+// -----
+
+def SPV_AccessChainOp : SPV_Op<"AccessChain", [NoSideEffect]> {
+  let summary = [{
+    Create a pointer into a composite object that can be used with OpLoad
+    and OpStore.
+  }];
+
+  let description = [{
+    Result Type must be an OpTypePointer. Its Type operand must be the type
+    reached by walking the Base’s type hierarchy down to the last provided
+    index in Indexes, and its Storage Class operand must be the same as the
+    Storage Class of Base.
+
+    Base must be a pointer, pointing to the base of a composite object.
+
+    Indexes walk the type hierarchy to the desired depth, potentially down
+    to scalar granularity. The first index in Indexes will select the top-
+    level member/element/component/element of the base composite. All
+    composite constituents use zero-based numbering, as described by their
+    OpType… instruction. The second index will apply similarly to that
+    result, and so on. Once any non-composite type is reached, there must be
+    no remaining (unused) indexes.
+
+     Each index in Indexes
+
+    - must be a scalar integer type,
+
+    - is treated as a signed count, and
+
+    - must be an OpConstant when indexing into a structure.
+
+    <!-- End of AutoGen section -->
+    ```
+    access-chain-op ::= ssa-id `=` `spv.AccessChain` ssa-use
+                        `[` ssa-use (',' ssa-use)* `]`
+                        `:` pointer-type
+    ```
+
+    #### Example:
+
+    ```mlir
+    %0 = "spv.constant"() { value = 1: i32} : () -> i32
+    %1 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
+    %2 = spv.AccessChain %1[%0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
+    %3 = spv.Load "Function" %2 ["Volatile"] : !spv.array<4xf32>
+    ```
+  }];
+
+  let arguments = (ins
+    SPV_AnyPtr:$base_ptr,
+    Variadic<SPV_Integer>:$indices
+  );
+
+  let results = (outs
+    SPV_AnyPtr:$component_ptr
+  );
+
+  let builders = [OpBuilderDAG<(ins "Value":$basePtr, "ValueRange":$indices)>];
+
+  let hasCanonicalizer = 1;
+}
+
+// -----
+
+def SPV_CopyMemoryOp : SPV_Op<"CopyMemory", []> {
+  let summary = [{
+    Copy from the memory pointed to by Source to the memory pointed to by
+    Target. Both operands must be non-void pointers and having the same <id>
+    Type operand in their OpTypePointer type declaration.  Matching Storage
+    Class is not required.  The amount of memory copied is the size of the
+    type pointed to. The copied type must have a fixed size; i.e., it cannot
+    be, nor include, any OpTypeRuntimeArray types.
+  }];
+
+  let description = [{
+    If present, any Memory Operands must begin with a memory operand
+    literal. If not present, it is the same as specifying the memory operand
+    None. Before version 1.4, at most one memory operands mask can be
+    provided. Starting with version 1.4 two masks can be provided, as
+    described in Memory Operands. If no masks or only one mask is present,
+    it applies to both Source and Target. If two masks are present, the
+    first applies to Target and cannot include MakePointerVisible, and the
+    second applies to Source and cannot include MakePointerAvailable.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    copy-memory-op ::= `spv.CopyMemory ` storage-class ssa-use
+                       storage-class ssa-use
+                       (`[` memory-access `]` (`, [` memory-access `]`)?)?
+                       ` : ` spirv-element-type
+    ```
+
+    #### Example:
+
+    ```mlir
+    %0 = spv.Variable : !spv.ptr<f32, Function>
+    %1 = spv.Variable : !spv.ptr<f32, Function>
+    spv.CopyMemory "Function" %0, "Function" %1 : f32
+    ```
+  }];
+
+  let arguments = (ins
+    SPV_AnyPtr:$target,
+    SPV_AnyPtr:$source,
+    OptionalAttr<SPV_MemoryAccessAttr>:$memory_access,
+    OptionalAttr<I32Attr>:$alignment,
+    OptionalAttr<SPV_MemoryAccessAttr>:$source_memory_access,
+    OptionalAttr<I32Attr>:$source_alignment
+  );
+
+  let results = (outs);
+
+  let verifier = [{ return verifyCopyMemory(*this); }];
+
+  let autogenSerialization = 0;
+}
+
+// -----
+
+def SPV_LoadOp : SPV_Op<"Load", []> {
+  let summary = "Load through a pointer.";
+
+  let description = [{
+    Result Type is the type of the loaded object. It must be a type with
+    fixed size; i.e., it cannot be, nor include, any OpTypeRuntimeArray
+    types.
+
+    Pointer is the pointer to load through.  Its type must be an
+    OpTypePointer whose Type operand is the same as Result Type.
+
+    If present, any Memory Operands must begin with a memory operand
+    literal. If not present, it is the same as specifying the memory operand
+    None.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    memory-access ::= `"None"` | `"Volatile"` | `"Aligned", ` integer-literal
+                    | `"NonTemporal"`
+
+    load-op ::= ssa-id ` = spv.Load ` storage-class ssa-use
+                (`[` memory-access `]`)? ` : ` spirv-element-type
+    ```
+
+    #### Example:
+
+    ```mlir
+    %0 = spv.Variable : !spv.ptr<f32, Function>
+    %1 = spv.Load "Function" %0 : f32
+    %2 = spv.Load "Function" %0 ["Volatile"] : f32
+    %3 = spv.Load "Function" %0 ["Aligned", 4] : f32
+    ```
+  }];
+
+  let arguments = (ins
+    SPV_AnyPtr:$ptr,
+    OptionalAttr<SPV_MemoryAccessAttr>:$memory_access,
+    OptionalAttr<I32Attr>:$alignment
+  );
+
+  let results = (outs
+    SPV_Type:$value
+  );
+
+  let builders = [
+    OpBuilderDAG<(ins "Value":$basePtr,
+      CArg<"IntegerAttr", "{}">:$memory_access,
+      CArg<"IntegerAttr", "{}">:$alignment)>
+  ];
+}
+
+// -----
+
+def SPV_StoreOp : SPV_Op<"Store", []> {
+  let summary = "Store through a pointer.";
+
+  let description = [{
+    Pointer is the pointer to store through.  Its type must be an
+    OpTypePointer whose Type operand is the same as the type of Object.
+
+    Object is the object to store.
+
+    If present, any Memory Operands must begin with a memory operand
+    literal. If not present, it is the same as specifying the memory operand
+    None.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    store-op ::= `spv.Store ` storage-class ssa-use `, ` ssa-use `, `
+                  (`[` memory-access `]`)? `:` spirv-element-type
+    ```
+
+    #### Example:
+
+    ```mlir
+    %0 = spv.Variable : !spv.ptr<f32, Function>
+    %1 = spv.FMul ... : f32
+    spv.Store "Function" %0, %1 : f32
+    spv.Store "Function" %0, %1 ["Volatile"] : f32
+    spv.Store "Function" %0, %1 ["Aligned", 4] : f32
+    ```
+  }];
+
+  let arguments = (ins
+    SPV_AnyPtr:$ptr,
+    SPV_Type:$value,
+    OptionalAttr<SPV_MemoryAccessAttr>:$memory_access,
+    OptionalAttr<I32Attr>:$alignment
+  );
+
+  let results = (outs);
+
+  let builders = [
+    OpBuilderDAG<(ins "Value":$ptr, "Value":$value,
+      CArg<"ArrayRef<NamedAttribute>", "{}">:$namedAttrs),
+    [{
+      $_state.addOperands(ptr);
+      $_state.addOperands(value);
+      $_state.addAttributes(namedAttrs);
+    }]>
+  ];
+}
+
+// -----
+
+def SPV_VariableOp : SPV_Op<"Variable", []> {
+  let summary = [{
+    Allocate an object in memory, resulting in a pointer to it, which can be
+    used with OpLoad and OpStore.
+  }];
+
+  let description = [{
+    Result Type must be an OpTypePointer. Its Type operand is the type of
+    object in memory.
+
+    Storage Class is the Storage Class of the memory holding the object.
+    Since the op is used to model function-level variables, the storage class
+    must be the `Function` Storage Class.
+
+    Initializer is optional. If Initializer is present, it will be the
+    initial value of the variable’s memory content. Initializer must be an
+    <id> from a constant instruction or a global (module scope) OpVariable
+    instruction. Initializer must have the same type as the type pointed to
+    by Result Type.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    variable-op ::= ssa-id `=` `spv.Variable` (`init(` ssa-use `)`)?
+                    attribute-dict? `:` spirv-pointer-type
+    ```
+
+    where `init` specifies initializer.
+
+    #### Example:
+
+    ```mlir
+    %0 = spv.constant ...
+
+    %1 = spv.Variable : !spv.ptr<f32, Function>
+    %2 = spv.Variable init(%0): !spv.ptr<f32, Function>
+    ```
+  }];
+
+  let arguments = (ins
+    SPV_StorageClassAttr:$storage_class,
+    Optional<AnyType>:$initializer
+  );
+
+  let results = (outs
+    SPV_AnyPtr:$pointer
+  );
+}
+
+#endif // MLIR_DIALECT_SPIRV_IR_MEMORY_OPS

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVMiscOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVMiscOps.td
new file mode 100644
index 000000000000..7e227c189564
--- /dev/null
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVMiscOps.td
@@ -0,0 +1,61 @@
+//===-- SPIRVBarrierOps.td - MLIR SPIR-V Barrier Ops -------*- 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 contains miscellaneous ops for the SPIR-V dialect. It corresponds
+// to "3.32.1. Miscellaneous Instructions" of the SPIR-V spec.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_SPIRV_IR_MISC_OPS
+#define MLIR_DIALECT_SPIRV_IR_MISC_OPS
+
+include "mlir/Dialect/SPIRV/IR/SPIRVBase.td"
+
+// -----
+
+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 
diff erent
+    bit pattern or abstract value resulting in possibly 
diff erent concrete,
+    abstract, or opaque values.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    undef-op ::= `spv.undef` `:` spirv-type
+    ```
+
+    #### Example:
+
+    ```mlir
+    %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(); }];
+
+  let hasOpcode = 0;
+  let autogenSerialization = 0;
+
+  let assemblyFormat = "attr-dict `:` type($result)";
+}
+
+// -----
+
+#endif // MLIR_DIALECT_SPIRV_IR_MISC_OPS

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.td
index 3621ff71f9c7..e5892012b98d 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.td
@@ -24,6 +24,7 @@
 include "mlir/Dialect/SPIRV/IR/SPIRVBase.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVArithmeticOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVAtomicOps.td"
+include "mlir/Dialect/SPIRV/IR/SPIRVBarrierOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVBitOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVCastOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVCompositeOps.td"
@@ -33,500 +34,11 @@ include "mlir/Dialect/SPIRV/IR/SPIRVGLSLOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVGroupOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVMatrixOps.td"
+include "mlir/Dialect/SPIRV/IR/SPIRVMemoryOps.td"
+include "mlir/Dialect/SPIRV/IR/SPIRVMiscOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVNonUniformOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVOCLOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td"
 include "mlir/Interfaces/SideEffectInterfaces.td"
 
-// -----
-
-def SPV_AccessChainOp : SPV_Op<"AccessChain", [NoSideEffect]> {
-  let summary = [{
-    Create a pointer into a composite object that can be used with OpLoad
-    and OpStore.
-  }];
-
-  let description = [{
-    Result Type must be an OpTypePointer. Its Type operand must be the type
-    reached by walking the Base’s type hierarchy down to the last provided
-    index in Indexes, and its Storage Class operand must be the same as the
-    Storage Class of Base.
-
-    Base must be a pointer, pointing to the base of a composite object.
-
-    Indexes walk the type hierarchy to the desired depth, potentially down
-    to scalar granularity. The first index in Indexes will select the top-
-    level member/element/component/element of the base composite. All
-    composite constituents use zero-based numbering, as described by their
-    OpType… instruction. The second index will apply similarly to that
-    result, and so on. Once any non-composite type is reached, there must be
-    no remaining (unused) indexes.
-
-     Each index in Indexes
-
-    - must be a scalar integer type,
-
-    - is treated as a signed count, and
-
-    - must be an OpConstant when indexing into a structure.
-
-    <!-- End of AutoGen section -->
-    ```
-    access-chain-op ::= ssa-id `=` `spv.AccessChain` ssa-use
-                        `[` ssa-use (',' ssa-use)* `]`
-                        `:` pointer-type
-    ```
-
-    #### Example:
-
-    ```mlir
-    %0 = "spv.constant"() { value = 1: i32} : () -> i32
-    %1 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
-    %2 = spv.AccessChain %1[%0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
-    %3 = spv.Load "Function" %2 ["Volatile"] : !spv.array<4xf32>
-    ```
-  }];
-
-  let arguments = (ins
-    SPV_AnyPtr:$base_ptr,
-    Variadic<SPV_Integer>:$indices
-  );
-
-  let results = (outs
-    SPV_AnyPtr:$component_ptr
-  );
-
-  let builders = [OpBuilderDAG<(ins "Value":$basePtr, "ValueRange":$indices)>];
-
-  let hasCanonicalizer = 1;
-}
-
-// -----
-
-def SPV_ControlBarrierOp : SPV_Op<"ControlBarrier", []> {
-  let summary = [{
-    Wait for other invocations of this module to reach the current point of
-    execution.
-  }];
-
-  let description = [{
-    All invocations of this module within Execution scope must reach this
-    point of execution before any invocation will proceed beyond it.
-
-    When Execution is Workgroup or larger, behavior is undefined if this
-    instruction is used in control flow that is non-uniform within
-    Execution. When Execution is Subgroup or Invocation, the behavior of
-    this instruction in non-uniform control flow is defined by the client
-    API.
-
-    If Semantics is not None, this instruction also serves as an
-    OpMemoryBarrier instruction, and must also perform and adhere to the
-    description and semantics of an OpMemoryBarrier instruction with the
-    same Memory and Semantics operands.  This allows atomically specifying
-    both a control barrier and a memory barrier (that is, without needing
-    two instructions). If Semantics is None, Memory is ignored.
-
-    Before version 1.3, it is only valid to use this instruction with
-    TessellationControl, GLCompute, or Kernel execution models. There is no
-    such restriction starting with version 1.3.
-
-    When used with the TessellationControl execution model, it also
-    implicitly synchronizes the Output Storage Class:  Writes to Output
-    variables performed by any invocation executed prior to a
-    OpControlBarrier will be visible to any other invocation after return
-    from that OpControlBarrier.
-
-    <!-- End of AutoGen section -->
-
-    ```
-    scope ::= `"CrossDevice"` | `"Device"` | `"Workgroup"` | ...
-
-    memory-semantics ::= `"None"` | `"Acquire"` | "Release"` | ...
-
-    control-barrier-op ::= `spv.ControlBarrier` scope, scope, memory-semantics
-    ```
-
-    #### Example:
-
-    ```mlir
-    spv.ControlBarrier "Workgroup", "Device", "Acquire|UniformMemory"
-
-    ```
-  }];
-
-  let arguments = (ins
-    SPV_ScopeAttr:$execution_scope,
-    SPV_ScopeAttr:$memory_scope,
-    SPV_MemorySemanticsAttr:$memory_semantics
-  );
-
-  let results = (outs);
-
-  let verifier = [{ return verifyMemorySemantics(*this); }];
-
-  let autogenSerialization = 0;
-
-  let assemblyFormat = [{
-    $execution_scope `,` $memory_scope `,` $memory_semantics attr-dict
-  }];
-}
-
-// -----
-
-def SPV_CopyMemoryOp : SPV_Op<"CopyMemory", []> {
-  let summary = [{
-    Copy from the memory pointed to by Source to the memory pointed to by
-    Target. Both operands must be non-void pointers and having the same <id>
-    Type operand in their OpTypePointer type declaration.  Matching Storage
-    Class is not required.  The amount of memory copied is the size of the
-    type pointed to. The copied type must have a fixed size; i.e., it cannot
-    be, nor include, any OpTypeRuntimeArray types.
-  }];
-
-  let description = [{
-    If present, any Memory Operands must begin with a memory operand
-    literal. If not present, it is the same as specifying the memory operand
-    None. Before version 1.4, at most one memory operands mask can be
-    provided. Starting with version 1.4 two masks can be provided, as
-    described in Memory Operands. If no masks or only one mask is present,
-    it applies to both Source and Target. If two masks are present, the
-    first applies to Target and cannot include MakePointerVisible, and the
-    second applies to Source and cannot include MakePointerAvailable.
-
-    <!-- End of AutoGen section -->
-
-    ```
-    copy-memory-op ::= `spv.CopyMemory ` storage-class ssa-use
-                       storage-class ssa-use
-                       (`[` memory-access `]` (`, [` memory-access `]`)?)?
-                       ` : ` spirv-element-type
-    ```
-
-    #### Example:
-
-    ```mlir
-    %0 = spv.Variable : !spv.ptr<f32, Function>
-    %1 = spv.Variable : !spv.ptr<f32, Function>
-    spv.CopyMemory "Function" %0, "Function" %1 : f32
-    ```
-  }];
-
-  let arguments = (ins
-    SPV_AnyPtr:$target,
-    SPV_AnyPtr:$source,
-    OptionalAttr<SPV_MemoryAccessAttr>:$memory_access,
-    OptionalAttr<I32Attr>:$alignment,
-    OptionalAttr<SPV_MemoryAccessAttr>:$source_memory_access,
-    OptionalAttr<I32Attr>:$source_alignment
-  );
-
-  let results = (outs);
-
-  let verifier = [{ return verifyCopyMemory(*this); }];
-
-  let autogenSerialization = 0;
-}
-
-// -----
-
-def SPV_ExecutionModeOp : SPV_Op<"ExecutionMode", [InModuleScope]> {
-  let summary = "Declare an execution mode for an entry point.";
-
-  let description = [{
-    Entry Point must be the Entry Point <id> operand of an OpEntryPoint
-    instruction.
-
-    Mode is the execution mode. See Execution Mode.
-
-    This instruction is only valid when the Mode operand is an execution
-    mode that takes no Extra Operands, or takes Extra Operands that are not
-    <id> operands.
-
-    <!-- End of AutoGen section -->
-
-    ```
-    execution-mode ::= "Invocations" | "SpacingEqual" |
-                       <and other SPIR-V execution modes...>
-
-    execution-mode-op ::= `spv.ExecutionMode ` ssa-use execution-mode
-                          (integer-literal (`, ` integer-literal)* )?
-    ```
-
-    #### Example:
-
-    ```mlir
-    spv.ExecutionMode @foo "ContractionOff"
-    spv.ExecutionMode @bar "LocalSizeHint", 3, 4, 5
-    ```
-  }];
-
-  let arguments = (ins
-    FlatSymbolRefAttr:$fn,
-    SPV_ExecutionModeAttr:$execution_mode,
-    I32ArrayAttr:$values
-  );
-
-  let results = (outs);
-
-  let verifier = [{ return success(); }];
-
-  let autogenSerialization = 0;
-
-  let builders = [
-    OpBuilderDAG<(ins "spirv::FuncOp":$function,
-      "spirv::ExecutionMode":$executionMode, "ArrayRef<int32_t>":$params)>];
-}
-
-// -----
-
-def SPV_LoadOp : SPV_Op<"Load", []> {
-  let summary = "Load through a pointer.";
-
-  let description = [{
-    Result Type is the type of the loaded object. It must be a type with
-    fixed size; i.e., it cannot be, nor include, any OpTypeRuntimeArray
-    types.
-
-    Pointer is the pointer to load through.  Its type must be an
-    OpTypePointer whose Type operand is the same as Result Type.
-
-    If present, any Memory Operands must begin with a memory operand
-    literal. If not present, it is the same as specifying the memory operand
-    None.
-
-    <!-- End of AutoGen section -->
-
-    ```
-    memory-access ::= `"None"` | `"Volatile"` | `"Aligned", ` integer-literal
-                    | `"NonTemporal"`
-
-    load-op ::= ssa-id ` = spv.Load ` storage-class ssa-use
-                (`[` memory-access `]`)? ` : ` spirv-element-type
-    ```
-
-    #### Example:
-
-    ```mlir
-    %0 = spv.Variable : !spv.ptr<f32, Function>
-    %1 = spv.Load "Function" %0 : f32
-    %2 = spv.Load "Function" %0 ["Volatile"] : f32
-    %3 = spv.Load "Function" %0 ["Aligned", 4] : f32
-    ```
-  }];
-
-  let arguments = (ins
-    SPV_AnyPtr:$ptr,
-    OptionalAttr<SPV_MemoryAccessAttr>:$memory_access,
-    OptionalAttr<I32Attr>:$alignment
-  );
-
-  let results = (outs
-    SPV_Type:$value
-  );
-
-  let builders = [
-    OpBuilderDAG<(ins "Value":$basePtr,
-      CArg<"IntegerAttr", "{}">:$memory_access,
-      CArg<"IntegerAttr", "{}">:$alignment)>
-  ];
-}
-
-// -----
-
-def SPV_MemoryBarrierOp : SPV_Op<"MemoryBarrier", []> {
-  let summary = "Control the order that memory accesses are observed.";
-
-  let description = [{
-    Ensures that memory accesses issued before this instruction will be
-    observed before memory accesses issued after this instruction. This
-    control is ensured only for memory accesses issued by this invocation
-    and observed by another invocation executing within Memory scope. If the
-    Vulkan memory model is declared, this ordering only applies to memory
-    accesses that use the NonPrivatePointer memory operand or
-    NonPrivateTexel image operand.
-
-    Semantics declares what kind of memory is being controlled and what kind
-    of control to apply.
-
-    To execute both a memory barrier and a control barrier, see
-    OpControlBarrier.
-
-    <!-- End of AutoGen section -->
-
-    ```
-    scope ::= `"CrossDevice"` | `"Device"` | `"Workgroup"` | ...
-
-    memory-semantics ::= `"None"` | `"Acquire"` | `"Release"` | ...
-
-    memory-barrier-op ::= `spv.MemoryBarrier` scope, memory-semantics
-    ```
-
-    #### Example:
-
-    ```mlir
-    spv.MemoryBarrier "Device", "Acquire|UniformMemory"
-
-    ```
-  }];
-
-  let arguments = (ins
-    SPV_ScopeAttr:$memory_scope,
-    SPV_MemorySemanticsAttr:$memory_semantics
-  );
-
-  let results = (outs);
-
-  let verifier = [{ return verifyMemorySemantics(*this); }];
-
-  let autogenSerialization = 0;
-
-  let assemblyFormat = "$memory_scope `,` $memory_semantics attr-dict";
-}
-
-// -----
-
-def SPV_StoreOp : SPV_Op<"Store", []> {
-  let summary = "Store through a pointer.";
-
-  let description = [{
-    Pointer is the pointer to store through.  Its type must be an
-    OpTypePointer whose Type operand is the same as the type of Object.
-
-    Object is the object to store.
-
-    If present, any Memory Operands must begin with a memory operand
-    literal. If not present, it is the same as specifying the memory operand
-    None.
-
-    <!-- End of AutoGen section -->
-
-    ```
-    store-op ::= `spv.Store ` storage-class ssa-use `, ` ssa-use `, `
-                  (`[` memory-access `]`)? `:` spirv-element-type
-    ```
-
-    #### Example:
-
-    ```mlir
-    %0 = spv.Variable : !spv.ptr<f32, Function>
-    %1 = spv.FMul ... : f32
-    spv.Store "Function" %0, %1 : f32
-    spv.Store "Function" %0, %1 ["Volatile"] : f32
-    spv.Store "Function" %0, %1 ["Aligned", 4] : f32
-    ```
-  }];
-
-  let arguments = (ins
-    SPV_AnyPtr:$ptr,
-    SPV_Type:$value,
-    OptionalAttr<SPV_MemoryAccessAttr>:$memory_access,
-    OptionalAttr<I32Attr>:$alignment
-  );
-
-  let results = (outs);
-
-  let builders = [
-    OpBuilderDAG<(ins "Value":$ptr, "Value":$value,
-      CArg<"ArrayRef<NamedAttribute>", "{}">:$namedAttrs),
-    [{
-      $_state.addOperands(ptr);
-      $_state.addOperands(value);
-      $_state.addAttributes(namedAttrs);
-    }]>
-  ];
-}
-
-// -----
-
-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 
diff erent
-    bit pattern or abstract value resulting in possibly 
diff erent concrete,
-    abstract, or opaque values.
-
-    <!-- End of AutoGen section -->
-
-    ```
-    undef-op ::= `spv.undef` `:` spirv-type
-    ```
-
-    #### Example:
-
-    ```mlir
-    %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(); }];
-
-  let hasOpcode = 0;
-  let autogenSerialization = 0;
-
-  let assemblyFormat = "attr-dict `:` type($result)";
-}
-
-// -----
-
-def SPV_VariableOp : SPV_Op<"Variable", []> {
-  let summary = [{
-    Allocate an object in memory, resulting in a pointer to it, which can be
-    used with OpLoad and OpStore.
-  }];
-
-  let description = [{
-    Result Type must be an OpTypePointer. Its Type operand is the type of
-    object in memory.
-
-    Storage Class is the Storage Class of the memory holding the object.
-    Since the op is used to model function-level variables, the storage class
-    must be the `Function` Storage Class.
-
-    Initializer is optional. If Initializer is present, it will be the
-    initial value of the variable’s memory content. Initializer must be an
-    <id> from a constant instruction or a global (module scope) OpVariable
-    instruction. Initializer must have the same type as the type pointed to
-    by Result Type.
-
-    <!-- End of AutoGen section -->
-
-    ```
-    variable-op ::= ssa-id `=` `spv.Variable` (`init(` ssa-use `)`)?
-                    attribute-dict? `:` spirv-pointer-type
-    ```
-
-    where `init` specifies initializer.
-
-    #### Example:
-
-    ```mlir
-    %0 = spv.constant ...
-
-    %1 = spv.Variable : !spv.ptr<f32, Function>
-    %2 = spv.Variable init(%0): !spv.ptr<f32, Function>
-    ```
-  }];
-
-  let arguments = (ins
-    SPV_StorageClassAttr:$storage_class,
-    Optional<AnyType>:$initializer
-  );
-
-  let results = (outs
-    SPV_AnyPtr:$pointer
-  );
-}
-
-// -----
-
 #endif // MLIR_DIALECT_SPIRV_IR_OPS

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td
index 88183f98c6d1..d4bf2861c960 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td
@@ -195,6 +195,56 @@ def SPV_EntryPointOp : SPV_Op<"EntryPoint", [InModuleScope]> {
 
 // -----
 
+def SPV_ExecutionModeOp : SPV_Op<"ExecutionMode", [InModuleScope]> {
+  let summary = "Declare an execution mode for an entry point.";
+
+  let description = [{
+    Entry Point must be the Entry Point <id> operand of an OpEntryPoint
+    instruction.
+
+    Mode is the execution mode. See Execution Mode.
+
+    This instruction is only valid when the Mode operand is an execution
+    mode that takes no Extra Operands, or takes Extra Operands that are not
+    <id> operands.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    execution-mode ::= "Invocations" | "SpacingEqual" |
+                       <and other SPIR-V execution modes...>
+
+    execution-mode-op ::= `spv.ExecutionMode ` ssa-use execution-mode
+                          (integer-literal (`, ` integer-literal)* )?
+    ```
+
+    #### Example:
+
+    ```mlir
+    spv.ExecutionMode @foo "ContractionOff"
+    spv.ExecutionMode @bar "LocalSizeHint", 3, 4, 5
+    ```
+  }];
+
+  let arguments = (ins
+    FlatSymbolRefAttr:$fn,
+    SPV_ExecutionModeAttr:$execution_mode,
+    I32ArrayAttr:$values
+  );
+
+  let results = (outs);
+
+  let verifier = [{ return success(); }];
+
+  let autogenSerialization = 0;
+
+  let builders = [
+    OpBuilderDAG<(ins "spirv::FuncOp":$function,
+      "spirv::ExecutionMode":$executionMode, "ArrayRef<int32_t>":$params)>];
+}
+
+// -----
+
 def SPV_FuncOp : SPV_Op<"func", [
     AutomaticAllocationScope, DeclareOpInterfaceMethods<CallableOpInterface>,
     FunctionLike, InModuleScope, IsolatedFromAbove, Symbol

diff  --git a/mlir/test/Dialect/SPIRV/IR/barrier-ops.mlir b/mlir/test/Dialect/SPIRV/IR/barrier-ops.mlir
new file mode 100644
index 000000000000..bd16d29add81
--- /dev/null
+++ b/mlir/test/Dialect/SPIRV/IR/barrier-ops.mlir
@@ -0,0 +1,49 @@
+// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
+
+//===----------------------------------------------------------------------===//
+// spv.ControlBarrier
+//===----------------------------------------------------------------------===//
+
+func @control_barrier_0() -> () {
+  // CHECK:  spv.ControlBarrier "Workgroup", "Device", "Acquire|UniformMemory"
+  spv.ControlBarrier "Workgroup", "Device", "Acquire|UniformMemory"
+  return
+}
+
+// -----
+
+func @control_barrier_1() -> () {
+  // expected-error @+1 {{invalid execution_scope attribute specification: "Something"}}
+  spv.ControlBarrier "Something", "Device", "Acquire|UniformMemory"
+  return
+}
+
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.MemoryBarrier
+//===----------------------------------------------------------------------===//
+
+func @memory_barrier_0() -> () {
+  // CHECK: spv.MemoryBarrier "Device", "Acquire|UniformMemory"
+  spv.MemoryBarrier "Device", "Acquire|UniformMemory"
+  return
+}
+
+// -----
+
+func @memory_barrier_1() -> () {
+  // CHECK: spv.MemoryBarrier "Workgroup", "Acquire"
+  spv.MemoryBarrier "Workgroup", "Acquire"
+  return
+}
+
+// -----
+
+func @memory_barrier_2() -> () {
+ // expected-error @+1 {{expected at most one of these four memory constraints to be set: `Acquire`, `Release`,`AcquireRelease` or `SequentiallyConsistent`}}
+  spv.MemoryBarrier "Device", "Acquire|Release"
+  return
+}
+

diff  --git a/mlir/test/Dialect/SPIRV/IR/bit-ops.mlir b/mlir/test/Dialect/SPIRV/IR/bit-ops.mlir
index 66998ec7084e..b5681e35d192 100644
--- a/mlir/test/Dialect/SPIRV/IR/bit-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/bit-ops.mlir
@@ -1,5 +1,79 @@
 // RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
 
+//===----------------------------------------------------------------------===//
+// spv.BitCount
+//===----------------------------------------------------------------------===//
+
+func @bitcount(%arg: i32) -> i32 {
+  // CHECK: spv.BitCount {{%.*}} : i32
+  %0 = spv.BitCount %arg : i32
+  spv.ReturnValue %0 : i32
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.BitFieldInsert
+//===----------------------------------------------------------------------===//
+
+func @bit_field_insert_vec(%base: vector<3xi32>, %insert: vector<3xi32>, %offset: i32, %count: i16) -> vector<3xi32> {
+  // CHECK: {{%.*}} = spv.BitFieldInsert {{%.*}}, {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i32, i16
+  %0 = spv.BitFieldInsert %base, %insert, %offset, %count : vector<3xi32>, i32, i16
+  spv.ReturnValue %0 : vector<3xi32>
+}
+
+// -----
+
+func @bit_field_insert_invalid_insert_type(%base: vector<3xi32>, %insert: vector<2xi32>, %offset: i32, %count: i16) -> vector<3xi32> {
+  // expected-error @+1 {{all of {base, insert, result} have same type}}
+  %0 = "spv.BitFieldInsert" (%base, %insert, %offset, %count) : (vector<3xi32>, vector<2xi32>, i32, i16) -> vector<3xi32>
+  spv.ReturnValue %0 : vector<3xi32>
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.BitFieldSExtract
+//===----------------------------------------------------------------------===//
+
+func @bit_field_s_extract_vec(%base: vector<3xi32>, %offset: i8, %count: i8) -> vector<3xi32> {
+  // CHECK: {{%.*}} = spv.BitFieldSExtract {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i8, i8
+  %0 = spv.BitFieldSExtract %base, %offset, %count : vector<3xi32>, i8, i8
+  spv.ReturnValue %0 : vector<3xi32>
+}
+
+//===----------------------------------------------------------------------===//
+// spv.BitFieldUExtract
+//===----------------------------------------------------------------------===//
+
+func @bit_field_u_extract_vec(%base: vector<3xi32>, %offset: i8, %count: i8) -> vector<3xi32> {
+  // CHECK: {{%.*}} = spv.BitFieldUExtract {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i8, i8
+  %0 = spv.BitFieldUExtract %base, %offset, %count : vector<3xi32>, i8, i8
+  spv.ReturnValue %0 : vector<3xi32>
+}
+
+// -----
+
+func @bit_field_u_extract_invalid_result_type(%base: vector<3xi32>, %offset: i32, %count: i16) -> vector<4xi32> {
+  // expected-error @+1 {{failed to verify that all of {base, result} have same type}}
+  %0 = "spv.BitFieldUExtract" (%base, %offset, %count) : (vector<3xi32>, i32, i16) -> vector<4xi32>
+  spv.ReturnValue %0 : vector<4xi32>
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.BitReverse
+//===----------------------------------------------------------------------===//
+
+func @bitreverse(%arg: i32) -> i32 {
+  // CHECK: spv.BitReverse {{%.*}} : i32
+  %0 = spv.BitReverse %arg : i32
+  spv.ReturnValue %0 : i32
+}
+
+// -----
+
 //===----------------------------------------------------------------------===//
 // spv.BitwiseOr
 //===----------------------------------------------------------------------===//
@@ -75,3 +149,59 @@ func @bitwise_and_float(%arg0: f16, %arg1: f16) -> f16 {
   %0 = spv.BitwiseAnd %arg0, %arg1 : f16
   return %0 : f16
 }
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.Not
+//===----------------------------------------------------------------------===//
+
+func @not(%arg: i32) -> i32 {
+  // CHECK: spv.Not {{%.*}} : i32
+  %0 = spv.Not %arg : i32
+  spv.ReturnValue %0 : i32
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.ShiftLeftLogical
+//===----------------------------------------------------------------------===//
+
+func @shift_left_logical(%arg0: i32, %arg1 : i16) -> i32 {
+  // CHECK: {{%.*}} = spv.ShiftLeftLogical {{%.*}}, {{%.*}} : i32, i16
+  %0 = spv.ShiftLeftLogical %arg0, %arg1: i32, i16
+  spv.ReturnValue %0 : i32
+}
+
+// -----
+
+func @shift_left_logical_invalid_result_type(%arg0: i32, %arg1 : i16) -> i16 {
+  // expected-error @+1 {{expected the same type for the first operand and result, but provided 'i32' and 'i16'}}
+  %0 = "spv.ShiftLeftLogical" (%arg0, %arg1) : (i32, i16) -> (i16)
+  spv.ReturnValue %0 : i16
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.ShiftRightArithmetic
+//===----------------------------------------------------------------------===//
+
+func @shift_right_arithmetic(%arg0: vector<4xi32>, %arg1 : vector<4xi8>) -> vector<4xi32> {
+  // CHECK: {{%.*}} = spv.ShiftRightArithmetic {{%.*}}, {{%.*}} : vector<4xi32>, vector<4xi8>
+  %0 = spv.ShiftRightArithmetic %arg0, %arg1: vector<4xi32>, vector<4xi8>
+  spv.ReturnValue %0 : vector<4xi32>
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.ShiftRightLogical
+//===----------------------------------------------------------------------===//
+
+func @shift_right_logical(%arg0: vector<2xi32>, %arg1 : vector<2xi8>) -> vector<2xi32> {
+  // CHECK: {{%.*}} = spv.ShiftRightLogical {{%.*}}, {{%.*}} : vector<2xi32>, vector<2xi8>
+  %0 = spv.ShiftRightLogical %arg0, %arg1: vector<2xi32>, vector<2xi8>
+  spv.ReturnValue %0 : vector<2xi32>
+}

diff  --git a/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir b/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
new file mode 100644
index 000000000000..c8c8edf258a9
--- /dev/null
+++ b/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
@@ -0,0 +1,262 @@
+// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
+
+//===----------------------------------------------------------------------===//
+// spv.Bitcast
+//===----------------------------------------------------------------------===//
+
+func @cast1(%arg0 : f32) {
+  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : f32 to i32
+  %0 = spv.Bitcast %arg0 : f32 to i32
+  return
+}
+
+func @cast2(%arg0 : vector<2xf32>) {
+  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<2xf32> to vector<2xi32>
+  %0 = spv.Bitcast %arg0 : vector<2xf32> to vector<2xi32>
+  return
+}
+
+func @cast3(%arg0 : vector<2xf32>) {
+  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<2xf32> to i64
+  %0 = spv.Bitcast %arg0 : vector<2xf32> to i64
+  return
+}
+
+func @cast4(%arg0 : !spv.ptr<f32, Function>) {
+  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : !spv.ptr<f32, Function> to !spv.ptr<i32, Function>
+  %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to !spv.ptr<i32, Function>
+  return
+}
+
+func @cast5(%arg0 : !spv.ptr<f32, Function>) {
+  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : !spv.ptr<f32, Function> to !spv.ptr<vector<2xi32>, Function>
+  %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to !spv.ptr<vector<2xi32>, Function>
+  return
+}
+
+func @cast6(%arg0 : vector<4xf32>) {
+  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<4xf32> to vector<2xi64>
+  %0 = spv.Bitcast %arg0 : vector<4xf32> to vector<2xi64>
+  return
+}
+
+// -----
+
+func @cast1(%arg0 : f32) {
+  // expected-error @+1 {{result type must be 
diff erent from operand type}}
+  %0 = spv.Bitcast %arg0 : f32 to f32
+  return
+}
+
+// -----
+
+func @cast1(%arg0 : f32) {
+  // expected-error @+1 {{mismatch in result type bitwidth 64 and operand type bitwidth 32}}
+  %0 = spv.Bitcast %arg0 : f32 to i64
+  return
+}
+
+// -----
+
+func @cast1(%arg0 : vector<2xf32>) {
+  // expected-error @+1 {{mismatch in result type bitwidth 96 and operand type bitwidth 64}}
+  %0 = spv.Bitcast %arg0 : vector<2xf32> to vector<3xf32>
+  return
+}
+
+// -----
+
+func @cast3(%arg0 : !spv.ptr<f32, Function>) {
+  // expected-error @+1 {{unhandled bit cast conversion from pointer type to non-pointer type}}
+  %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to i64
+  return
+}
+
+// -----
+
+func @cast3(%arg0 : i64) {
+  // expected-error @+1 {{unhandled bit cast conversion from non-pointer type to pointer type}}
+  %0 = spv.Bitcast %arg0 : i64 to !spv.ptr<f32, Function>
+  return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.ConvertFToS
+//===----------------------------------------------------------------------===//
+
+func @convert_f_to_s_scalar(%arg0 : f32) -> i32 {
+  // CHECK: {{%.*}} = spv.ConvertFToS {{%.*}} : f32 to i32
+  %0 = spv.ConvertFToS %arg0 : f32 to i32
+  spv.ReturnValue %0 : i32
+}
+
+// -----
+
+func @convert_f64_to_s32_scalar(%arg0 : f64) -> i32 {
+  // CHECK: {{%.*}} = spv.ConvertFToS {{%.*}} : f64 to i32
+  %0 = spv.ConvertFToS %arg0 : f64 to i32
+  spv.ReturnValue %0 : i32
+}
+
+// -----
+
+func @convert_f_to_s_vector(%arg0 : vector<3xf32>) -> vector<3xi32> {
+  // CHECK: {{%.*}} = spv.ConvertFToS {{%.*}} : vector<3xf32> to vector<3xi32>
+  %0 = spv.ConvertFToS %arg0 : vector<3xf32> to vector<3xi32>
+  spv.ReturnValue %0 : vector<3xi32>
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.ConvertFToU
+//===----------------------------------------------------------------------===//
+
+func @convert_f_to_u_scalar(%arg0 : f32) -> i32 {
+  // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : f32 to i32
+  %0 = spv.ConvertFToU %arg0 : f32 to i32
+  spv.ReturnValue %0 : i32
+}
+
+// -----
+
+func @convert_f64_to_u32_scalar(%arg0 : f64) -> i32 {
+  // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : f64 to i32
+  %0 = spv.ConvertFToU %arg0 : f64 to i32
+  spv.ReturnValue %0 : i32
+}
+
+// -----
+
+func @convert_f_to_u_vector(%arg0 : vector<3xf32>) -> vector<3xi32> {
+  // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : vector<3xf32> to vector<3xi32>
+  %0 = spv.ConvertFToU %arg0 : vector<3xf32> to vector<3xi32>
+  spv.ReturnValue %0 : vector<3xi32>
+}
+
+// -----
+
+func @convert_f_to_u_coopmatrix(%arg0 : !spv.coopmatrix<8x16xf32, Subgroup>) {
+  // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : !spv.coopmatrix<8x16xf32, Subgroup> to !spv.coopmatrix<8x16xi32, Subgroup>
+  %0 = spv.ConvertFToU %arg0 : !spv.coopmatrix<8x16xf32, Subgroup> to !spv.coopmatrix<8x16xi32, Subgroup>
+  spv.Return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.ConvertSToF
+//===----------------------------------------------------------------------===//
+
+func @convert_s_to_f_scalar(%arg0 : i32) -> f32 {
+  // CHECK: {{%.*}} = spv.ConvertSToF {{%.*}} : i32 to f32
+  %0 = spv.ConvertSToF %arg0 : i32 to f32
+  spv.ReturnValue %0 : f32
+}
+
+// -----
+
+func @convert_s64_to_f32_scalar(%arg0 : i64) -> f32 {
+  // CHECK: {{%.*}} = spv.ConvertSToF {{%.*}} : i64 to f32
+  %0 = spv.ConvertSToF %arg0 : i64 to f32
+  spv.ReturnValue %0 : f32
+}
+
+// -----
+
+func @convert_s_to_f_vector(%arg0 : vector<3xi32>) -> vector<3xf32> {
+  // CHECK: {{%.*}} = spv.ConvertSToF {{%.*}} : vector<3xi32> to vector<3xf32>
+  %0 = spv.ConvertSToF %arg0 : vector<3xi32> to vector<3xf32>
+  spv.ReturnValue %0 : vector<3xf32>
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.ConvertUToF
+//===----------------------------------------------------------------------===//
+
+func @convert_u_to_f_scalar(%arg0 : i32) -> f32 {
+  // CHECK: {{%.*}} = spv.ConvertUToF {{%.*}} : i32 to f32
+  %0 = spv.ConvertUToF %arg0 : i32 to f32
+  spv.ReturnValue %0 : f32
+}
+
+// -----
+
+func @convert_u64_to_f32_scalar(%arg0 : i64) -> f32 {
+  // CHECK: {{%.*}} = spv.ConvertUToF {{%.*}} : i64 to f32
+  %0 = spv.ConvertUToF %arg0 : i64 to f32
+  spv.ReturnValue %0 : f32
+}
+
+// -----
+
+func @convert_u_to_f_vector(%arg0 : vector<3xi32>) -> vector<3xf32> {
+  // CHECK: {{%.*}} = spv.ConvertUToF {{%.*}} : vector<3xi32> to vector<3xf32>
+  %0 = spv.ConvertUToF %arg0 : vector<3xi32> to vector<3xf32>
+  spv.ReturnValue %0 : vector<3xf32>
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.FConvert
+//===----------------------------------------------------------------------===//
+
+func @f_convert_scalar(%arg0 : f32) -> f64 {
+  // CHECK: {{%.*}} = spv.FConvert {{%.*}} : f32 to f64
+  %0 = spv.FConvert %arg0 : f32 to f64
+  spv.ReturnValue %0 : f64
+}
+
+// -----
+
+func @f_convert_vector(%arg0 : vector<3xf32>) -> vector<3xf64> {
+  // CHECK: {{%.*}} = spv.FConvert {{%.*}} : vector<3xf32> to vector<3xf64>
+  %0 = spv.FConvert %arg0 : vector<3xf32> to vector<3xf64>
+  spv.ReturnValue %0 : vector<3xf64>
+}
+
+// -----
+
+func @f_convert_coop_matrix(%arg0 : !spv.coopmatrix<8x16xf32, Subgroup>) {
+  // CHECK: {{%.*}} = spv.FConvert {{%.*}} : !spv.coopmatrix<8x16xf32, Subgroup> to !spv.coopmatrix<8x16xf64, Subgroup>
+  %0 = spv.FConvert %arg0 : !spv.coopmatrix<8x16xf32, Subgroup> to !spv.coopmatrix<8x16xf64, Subgroup>
+  spv.Return
+}
+
+// -----
+
+func @f_convert_vector(%arg0 : f32) -> f32 {
+  // expected-error @+1 {{expected the 
diff erent bit widths for operand type and result type, but provided 'f32' and 'f32'}}
+  %0 = spv.FConvert %arg0 : f32 to f32
+  spv.ReturnValue %0 : f32
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.SConvert
+//===----------------------------------------------------------------------===//
+
+func @s_convert_scalar(%arg0 : i32) -> i64 {
+  // CHECK: {{%.*}} = spv.SConvert {{%.*}} : i32 to i64
+  %0 = spv.SConvert %arg0 : i32 to i64
+  spv.ReturnValue %0 : i64
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.UConvert
+//===----------------------------------------------------------------------===//
+
+func @u_convert_scalar(%arg0 : i32) -> i64 {
+  // CHECK: {{%.*}} = spv.UConvert {{%.*}} : i32 to i64
+  %0 = spv.UConvert %arg0 : i32 to i64
+  spv.ReturnValue %0 : i64
+}
+

diff  --git a/mlir/test/Dialect/SPIRV/IR/group-ops.mlir b/mlir/test/Dialect/SPIRV/IR/group-ops.mlir
index 55a07270a348..c71cc3602b2e 100644
--- a/mlir/test/Dialect/SPIRV/IR/group-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/group-ops.mlir
@@ -64,6 +64,17 @@ func @group_broadcast_negative_locid_vec4(%value: f32, %localid: vector<4xi32> )
 
 // -----
 
+//===----------------------------------------------------------------------===//
+// spv.SubgroupBallotKHR
+//===----------------------------------------------------------------------===//
+
+func @subgroup_ballot(%predicate: i1) -> vector<4xi32> {
+  %0 = spv.SubgroupBallotKHR %predicate: vector<4xi32>
+  return %0: vector<4xi32>
+}
+
+// -----
+
 //===----------------------------------------------------------------------===//
 // spv.SubgroupBlockReadINTEL
 //===----------------------------------------------------------------------===//
@@ -100,4 +111,4 @@ func @subgroup_block_write_intel_vector(%ptr : !spv.ptr<i32, StorageBuffer>, %va
   // CHECK: spv.SubgroupBlockWriteINTEL %{{.*}}, %{{.*}} : vector<3xi32>
   spv.SubgroupBlockWriteINTEL "StorageBuffer" %ptr, %value : vector<3xi32>
   return
-}
\ No newline at end of file
+}

diff  --git a/mlir/test/Dialect/SPIRV/IR/logical-ops.mlir b/mlir/test/Dialect/SPIRV/IR/logical-ops.mlir
index d102ae98d3ae..baf8b45d7eaf 100644
--- a/mlir/test/Dialect/SPIRV/IR/logical-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/logical-ops.mlir
@@ -32,6 +32,217 @@ func @inotequal_vector(%arg0: vector<4xi32>, %arg1: vector<4xi32>) -> vector<4xi
 
 // -----
 
+//===----------------------------------------------------------------------===//
+// spv.LogicalAnd
+//===----------------------------------------------------------------------===//
+
+func @logicalBinary(%arg0 : i1, %arg1 : i1, %arg2 : i1)
+{
+  // CHECK: [[TMP:%.*]] = spv.LogicalAnd {{%.*}}, {{%.*}} : i1
+  %0 = spv.LogicalAnd %arg0, %arg1 : i1
+  // CHECK: {{%.*}} = spv.LogicalAnd [[TMP]], {{%.*}} : i1
+  %1 = spv.LogicalAnd %0, %arg2 : i1
+  return
+}
+
+func @logicalBinary2(%arg0 : vector<4xi1>, %arg1 : vector<4xi1>)
+{
+  // CHECK: {{%.*}} = spv.LogicalAnd {{%.*}}, {{%.*}} : vector<4xi1>
+  %0 = spv.LogicalAnd %arg0, %arg1 : vector<4xi1>
+  return
+}
+
+// -----
+
+func @logicalBinary(%arg0 : i1, %arg1 : i1)
+{
+  // expected-error @+2 {{expected ':'}}
+  %0 = spv.LogicalAnd %arg0, %arg1
+  return
+}
+
+// -----
+
+func @logicalBinary(%arg0 : i1, %arg1 : i1)
+{
+  // expected-error @+2 {{expected non-function type}}
+  %0 = spv.LogicalAnd %arg0, %arg1 :
+  return
+}
+
+// -----
+
+func @logicalBinary(%arg0 : i1, %arg1 : i1)
+{
+  // expected-error @+1 {{custom op 'spv.LogicalAnd' expected 2 operands}}
+  %0 = spv.LogicalAnd %arg0 : i1
+  return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.LogicalNot
+//===----------------------------------------------------------------------===//
+
+func @logicalUnary(%arg0 : i1, %arg1 : i1)
+{
+  // CHECK: [[TMP:%.*]] = spv.LogicalNot {{%.*}} : i1
+  %0 = spv.LogicalNot %arg0 : i1
+  // CHECK: {{%.*}} = spv.LogicalNot [[TMP]] : i1
+  %1 = spv.LogicalNot %0 : i1
+  return
+}
+
+func @logicalUnary2(%arg0 : vector<4xi1>)
+{
+  // CHECK: {{%.*}} = spv.LogicalNot {{%.*}} : vector<4xi1>
+  %0 = spv.LogicalNot %arg0 : vector<4xi1>
+  return
+}
+
+// -----
+
+func @logicalUnary(%arg0 : i1)
+{
+  // expected-error @+2 {{expected ':'}}
+  %0 = spv.LogicalNot %arg0
+  return
+}
+
+// -----
+
+func @logicalUnary(%arg0 : i1)
+{
+  // expected-error @+2 {{expected non-function type}}
+  %0 = spv.LogicalNot %arg0 :
+  return
+}
+
+// -----
+
+func @logicalUnary(%arg0 : i1)
+{
+  // expected-error @+1 {{expected SSA operand}}
+  %0 = spv.LogicalNot : i1
+  return
+}
+
+// -----
+
+func @logicalUnary(%arg0 : i32)
+{
+  // expected-error @+1 {{operand #0 must be bool or vector of bool values of length 2/3/4/8/16, but got 'i32'}}
+  %0 = spv.LogicalNot %arg0 : i32
+  return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.SelectOp
+//===----------------------------------------------------------------------===//
+
+func @select_op_bool(%arg0: i1) -> () {
+  %0 = spv.constant true
+  %1 = spv.constant false
+  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, i1
+  %2 = spv.Select %arg0, %0, %1 : i1, i1
+  return
+}
+
+func @select_op_int(%arg0: i1) -> () {
+  %0 = spv.constant 2 : i32
+  %1 = spv.constant 3 : i32
+  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, i32
+  %2 = spv.Select %arg0, %0, %1 : i1, i32
+  return
+}
+
+func @select_op_float(%arg0: i1) -> () {
+  %0 = spv.constant 2.0 : f32
+  %1 = spv.constant 3.0 : f32
+  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, f32
+  %2 = spv.Select %arg0, %0, %1 : i1, f32
+  return
+}
+
+func @select_op_ptr(%arg0: i1) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  %1 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, !spv.ptr<f32, Function>
+  %2 = spv.Select %arg0, %0, %1 : i1, !spv.ptr<f32, Function>
+  return
+}
+
+func @select_op_vec(%arg0: i1) -> () {
+  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
+  %1 = spv.constant dense<[5.0, 6.0, 7.0]> : vector<3xf32>
+  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, vector<3xf32>
+  %2 = spv.Select %arg0, %0, %1 : i1, vector<3xf32>
+  return
+}
+
+func @select_op_vec_condn_vec(%arg0: vector<3xi1>) -> () {
+  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
+  %1 = spv.constant dense<[5.0, 6.0, 7.0]> : vector<3xf32>
+  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi1>, vector<3xf32>
+  %2 = spv.Select %arg0, %0, %1 : vector<3xi1>, vector<3xf32>
+  return
+}
+
+// -----
+
+func @select_op(%arg0: i1) -> () {
+  %0 = spv.constant 2 : i32
+  %1 = spv.constant 3 : i32
+  // expected-error @+2 {{expected ','}}
+  %2 = spv.Select %arg0, %0, %1 : i1
+  return
+}
+
+// -----
+
+func @select_op(%arg1: vector<3xi1>) -> () {
+  %0 = spv.constant 2 : i32
+  %1 = spv.constant 3 : i32
+  // expected-error @+1 {{result expected to be of vector type when condition is of vector type}}
+  %2 = spv.Select %arg1, %0, %1 : vector<3xi1>, i32
+  return
+}
+
+// -----
+
+func @select_op(%arg1: vector<4xi1>) -> () {
+  %0 = spv.constant dense<[2, 3, 4]> : vector<3xi32>
+  %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32>
+  // expected-error @+1 {{result should have the same number of elements as the condition when condition is of vector type}}
+  %2 = spv.Select %arg1, %0, %1 : vector<4xi1>, vector<3xi32>
+  return
+}
+
+// -----
+
+func @select_op(%arg1: vector<4xi1>) -> () {
+  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
+  %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32>
+  // expected-error @+1 {{all of {true_value, false_value, result} have same type}}
+  %2 = "spv.Select"(%arg1, %0, %1) : (vector<4xi1>, vector<3xf32>, vector<3xi32>) -> vector<3xi32>
+  return
+}
+
+// -----
+
+func @select_op(%arg1: vector<4xi1>) -> () {
+  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
+  %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32>
+  // expected-error @+1 {{all of {true_value, false_value, result} have same type}}
+  %2 = "spv.Select"(%arg1, %1, %0) : (vector<4xi1>, vector<3xi32>, vector<3xf32>) -> vector<3xi32>
+  return
+}
+
+// -----
+
 //===----------------------------------------------------------------------===//
 // spv.SGreaterThan
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/test/Dialect/SPIRV/IR/memory-ops.mlir b/mlir/test/Dialect/SPIRV/IR/memory-ops.mlir
new file mode 100644
index 000000000000..d6f50a6be6f5
--- /dev/null
+++ b/mlir/test/Dialect/SPIRV/IR/memory-ops.mlir
@@ -0,0 +1,629 @@
+// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
+
+//===----------------------------------------------------------------------===//
+// spv.AccessChain
+//===----------------------------------------------------------------------===//
+
+func @access_chain_struct() -> () {
+  %0 = spv.constant 1: i32
+  %1 = spv.Variable : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>
+  // CHECK: spv.AccessChain {{.*}}[{{.*}}, {{.*}}] : !spv.ptr<!spv.struct<(f32, !spv.array<4 x f32>)>, Function>
+  %2 = spv.AccessChain %1[%0, %0] : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>, i32, i32
+  return
+}
+
+func @access_chain_1D_array(%arg0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.array<4xf32>, Function>
+  // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.array<4 x f32>, Function>
+  %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.array<4xf32>, Function>, i32
+  return
+}
+
+func @access_chain_2D_array_1(%arg0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
+  // CHECK: spv.AccessChain {{.*}}[{{.*}}, {{.*}}] : !spv.ptr<!spv.array<4 x !spv.array<4 x f32>>, Function>
+  %1 = spv.AccessChain %0[%arg0, %arg0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32, i32
+  %2 = spv.Load "Function" %1 ["Volatile"] : f32
+  return
+}
+
+func @access_chain_2D_array_2(%arg0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
+  // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.array<4 x !spv.array<4 x f32>>, Function>
+  %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32
+  %2 = spv.Load "Function" %1 ["Volatile"] : !spv.array<4xf32>
+  return
+}
+
+func @access_chain_rtarray(%arg0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.rtarray<f32>, Function>
+  // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.rtarray<f32>, Function>
+  %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.rtarray<f32>, Function>, i32
+  %2 = spv.Load "Function" %1 ["Volatile"] : f32
+  return
+}
+
+// -----
+
+func @access_chain_non_composite() -> () {
+  %0 = spv.constant 1: i32
+  %1 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{cannot extract from non-composite type 'f32' with index 0}}
+  %2 = spv.AccessChain %1[%0] : !spv.ptr<f32, Function>, i32
+  return
+}
+
+// -----
+
+func @access_chain_no_indices(%index0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
+  // expected-error @+1 {{expected at least one index}}
+  %1 = spv.AccessChain %0[] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32
+  return
+}
+
+// -----
+
+func @access_chain_missing_comma(%index0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
+  // expected-error @+1 {{expected ','}}
+  %1 = spv.AccessChain %0[%index0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> i32
+  return
+}
+
+// -----
+
+func @access_chain_invalid_indices_types_count(%index0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
+  // expected-error @+1 {{'spv.AccessChain' op indices types' count must be equal to indices info count}}
+  %1 = spv.AccessChain %0[%index0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32, i32
+  return
+}
+
+// -----
+
+func @access_chain_missing_indices_type(%index0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
+  // expected-error @+1 {{'spv.AccessChain' op indices types' count must be equal to indices info count}}
+  %1 = spv.AccessChain %0[%index0, %index0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32
+  return
+}
+
+// -----
+
+func @access_chain_invalid_type(%index0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
+  %1 = spv.Load "Function" %0 ["Volatile"] : !spv.array<4x!spv.array<4xf32>>
+  // expected-error @+1 {{expected a pointer to composite type, but provided '!spv.array<4 x !spv.array<4 x f32>>'}}
+  %2 = spv.AccessChain %1[%index0] : !spv.array<4x!spv.array<4xf32>>, i32
+  return
+}
+
+// -----
+
+func @access_chain_invalid_index_1(%index0 : i32) -> () {
+   %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
+  // expected-error @+1 {{expected SSA operand}}
+  %1 = spv.AccessChain %0[%index, 4] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32, i32
+  return
+}
+
+// -----
+
+func @access_chain_invalid_index_2(%index0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>
+  // expected-error @+1 {{index must be an integer spv.constant to access element of spv.struct}}
+  %1 = spv.AccessChain %0[%index0, %index0] : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>, i32, i32
+  return
+}
+
+// -----
+
+func @access_chain_invalid_constant_type_1() -> () {
+  %0 = std.constant 1: i32
+  %1 = spv.Variable : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>
+  // expected-error @+1 {{index must be an integer spv.constant to access element of spv.struct, but provided std.constant}}
+  %2 = spv.AccessChain %1[%0, %0] : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>, i32, i32
+  return
+}
+
+// -----
+
+func @access_chain_out_of_bounds() -> () {
+  %index0 = "spv.constant"() { value = 12: i32} : () -> i32
+  %0 = spv.Variable : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>
+  // expected-error @+1 {{'spv.AccessChain' op index 12 out of bounds for '!spv.struct<(f32, !spv.array<4 x f32>)>'}}
+  %1 = spv.AccessChain %0[%index0, %index0] : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>, i32, i32
+  return
+}
+
+// -----
+
+func @access_chain_invalid_accessing_type(%index0 : i32) -> () {
+  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
+  // expected-error @+1 {{cannot extract from non-composite type 'f32' with index 0}}
+  %1 = spv.AccessChain %0[%index, %index0, %index0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32, i32, i32
+  return
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.LoadOp
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @simple_load
+func @simple_load() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Load "Function" %{{.*}} : f32
+  %1 = spv.Load "Function" %0 : f32
+  return
+}
+
+// CHECK-LABEL: @load_none_access
+func @load_none_access() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Load "Function" %{{.*}} ["None"] : f32
+  %1 = spv.Load "Function" %0 ["None"] : f32
+  return
+}
+
+// CHECK-LABEL: @volatile_load
+func @volatile_load() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Load "Function" %{{.*}} ["Volatile"] : f32
+  %1 = spv.Load "Function" %0 ["Volatile"] : f32
+  return
+}
+
+// CHECK-LABEL: @aligned_load
+func @aligned_load() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Load "Function" %{{.*}} ["Aligned", 4] : f32
+  %1 = spv.Load "Function" %0 ["Aligned", 4] : f32
+  return
+}
+
+// CHECK-LABEL: @volatile_aligned_load
+func @volatile_aligned_load() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Load "Function" %{{.*}} ["Volatile|Aligned", 4] : f32
+  %1 = spv.Load "Function" %0 ["Volatile|Aligned", 4] : f32
+  return
+}
+
+// -----
+
+// CHECK-LABEL: load_none_access
+func @load_none_access() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Load
+  // CHECK-SAME: ["None"]
+  %1 = "spv.Load"(%0) {memory_access = 0 : i32} : (!spv.ptr<f32, Function>) -> (f32)
+  return
+}
+
+// CHECK-LABEL: volatile_load
+func @volatile_load() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Load
+  // CHECK-SAME: ["Volatile"]
+  %1 = "spv.Load"(%0) {memory_access = 1 : i32} : (!spv.ptr<f32, Function>) -> (f32)
+  return
+}
+
+// CHECK-LABEL: aligned_load
+func @aligned_load() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Load
+  // CHECK-SAME: ["Aligned", 4]
+  %1 = "spv.Load"(%0) {memory_access = 2 : i32, alignment = 4 : i32} : (!spv.ptr<f32, Function>) -> (f32)
+  return
+}
+
+// CHECK-LABEL: volatile_aligned_load
+func @volatile_aligned_load() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Load
+  // CHECK-SAME: ["Volatile|Aligned", 4]
+  %1 = "spv.Load"(%0) {memory_access = 3 : i32, alignment = 4 : i32} : (!spv.ptr<f32, Function>) -> (f32)
+  return
+}
+
+// -----
+
+func @simple_load_missing_storageclass() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected non-function type}}
+  %1 = spv.Load %0 : f32
+  return
+}
+
+// -----
+
+func @simple_load_missing_operand() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected SSA operand}}
+  %1 = spv.Load "Function" : f32
+  return
+}
+
+// -----
+
+func @simple_load_missing_rettype() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+2 {{expected ':'}}
+  %1 = spv.Load "Function" %0
+  return
+}
+
+// -----
+
+func @volatile_load_missing_lbrace() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ':'}}
+  %1 = spv.Load "Function" %0 "Volatile"] : f32
+  return
+}
+
+// -----
+
+func @volatile_load_missing_rbrace() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ']'}}
+  %1 = spv.Load "Function" %0 ["Volatile"} : f32
+  return
+}
+
+// -----
+
+func @aligned_load_missing_alignment() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ','}}
+  %1 = spv.Load "Function" %0 ["Aligned"] : f32
+  return
+}
+
+// -----
+
+func @aligned_load_missing_comma() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ','}}
+  %1 = spv.Load "Function" %0 ["Aligned" 4] : f32
+  return
+}
+
+// -----
+
+func @load_incorrect_attributes() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ']'}}
+  %1 = spv.Load "Function" %0 ["Volatile", 4] : f32
+  return
+}
+
+// -----
+
+func @load_unknown_memory_access() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{custom op 'spv.Load' invalid memory_access attribute specification: "Something"}}
+  %1 = spv.Load "Function" %0 ["Something"] : f32
+  return
+}
+
+// -----
+
+func @load_unknown_memory_access() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{custom op 'spv.Load' invalid memory_access attribute specification: "Volatile|Something"}}
+  %1 = spv.Load "Function" %0 ["Volatile|Something"] : f32
+  return
+}
+
+// -----
+
+func @load_unknown_memory_access() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{failed to satisfy constraint: valid SPIR-V MemoryAccess}}
+  %1 = "spv.Load"(%0) {memory_access = 0x80000000 : i32} : (!spv.ptr<f32, Function>) -> (f32)
+  return
+}
+
+// -----
+
+func @aligned_load_incorrect_attributes() -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ']'}}
+  %1 = spv.Load "Function" %0 ["Aligned", 4, 23] : f32
+  return
+}
+
+// -----
+
+spv.module Logical GLSL450 {
+  spv.globalVariable @var0 : !spv.ptr<f32, Input>
+  // CHECK_LABEL: @simple_load
+  spv.func @simple_load() -> () "None" {
+    // CHECK: spv.Load "Input" {{%.*}} : f32
+    %0 = spv.mlir.addressof @var0 : !spv.ptr<f32, Input>
+    %1 = spv.Load "Input" %0 : f32
+    spv.Return
+  }
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.StoreOp
+//===----------------------------------------------------------------------===//
+
+func @simple_store(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Store  "Function" %0, %arg0 : f32
+  spv.Store  "Function" %0, %arg0 : f32
+  return
+}
+
+// CHECK_LABEL: @volatile_store
+func @volatile_store(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Store  "Function" %0, %arg0 ["Volatile"] : f32
+  spv.Store  "Function" %0, %arg0 ["Volatile"] : f32
+  return
+}
+
+// CHECK_LABEL: @aligned_store
+func @aligned_store(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // CHECK: spv.Store  "Function" %0, %arg0 ["Aligned", 4] : f32
+  spv.Store  "Function" %0, %arg0 ["Aligned", 4] : f32
+  return
+}
+
+// -----
+
+func @simple_store_missing_ptr_type(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected non-function type}}
+  spv.Store  %0, %arg0 : f32
+  return
+}
+
+// -----
+
+func @simple_store_missing_operand(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{custom op 'spv.Store' invalid operand}} : f32
+  spv.Store  "Function" , %arg0 : f32
+  return
+}
+
+// -----
+
+func @simple_store_missing_operand(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{custom op 'spv.Store' expected 2 operands}} : f32
+  spv.Store  "Function" %0 : f32
+  return
+}
+
+// -----
+
+func @volatile_store_missing_lbrace(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ':'}}
+  spv.Store  "Function" %0, %arg0 "Volatile"] : f32
+  return
+}
+
+// -----
+
+func @volatile_store_missing_rbrace(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ']'}}
+  spv.Store "Function" %0, %arg0 ["Volatile"} : f32
+  return
+}
+
+// -----
+
+func @aligned_store_missing_alignment(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ','}}
+  spv.Store  "Function" %0, %arg0 ["Aligned"] : f32
+  return
+}
+
+// -----
+
+func @aligned_store_missing_comma(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ','}}
+  spv.Store  "Function" %0, %arg0 ["Aligned" 4] : f32
+  return
+}
+
+// -----
+
+func @load_incorrect_attributes(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ']'}}
+  spv.Store  "Function" %0, %arg0 ["Volatile", 4] : f32
+  return
+}
+
+// -----
+
+func @aligned_store_incorrect_attributes(%arg0 : f32) -> () {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{expected ']'}}
+  spv.Store  "Function" %0, %arg0 ["Aligned", 4, 23] : f32
+  return
+}
+
+// -----
+
+spv.module Logical GLSL450 {
+  spv.globalVariable @var0 : !spv.ptr<f32, Input>
+  spv.func @simple_store(%arg0 : f32) -> () "None" {
+    %0 = spv.mlir.addressof @var0 : !spv.ptr<f32, Input>
+    // CHECK: spv.Store  "Input" {{%.*}}, {{%.*}} : f32
+    spv.Store  "Input" %0, %arg0 : f32
+    spv.Return
+  }
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.Variable
+//===----------------------------------------------------------------------===//
+
+func @variable(%arg0: f32) -> () {
+  // CHECK: spv.Variable : !spv.ptr<f32, Function>
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  return
+}
+
+// -----
+
+func @variable_init_normal_constant() -> () {
+  %0 = spv.constant 4.0 : f32
+  // CHECK: spv.Variable init(%0) : !spv.ptr<f32, Function>
+  %1 = spv.Variable init(%0) : !spv.ptr<f32, Function>
+  return
+}
+
+// -----
+
+spv.module Logical GLSL450 {
+  spv.globalVariable @global : !spv.ptr<f32, Workgroup>
+  spv.func @variable_init_global_variable() -> () "None" {
+    %0 = spv.mlir.addressof @global : !spv.ptr<f32, Workgroup>
+    // CHECK: spv.Variable init({{.*}}) : !spv.ptr<!spv.ptr<f32, Workgroup>, Function>
+    %1 = spv.Variable init(%0) : !spv.ptr<!spv.ptr<f32, Workgroup>, Function>
+    spv.Return
+  }
+}
+
+// -----
+
+spv.module Logical GLSL450 {
+  spv.specConstant @sc = 42 : i32
+  // CHECK-LABEL: @variable_init_spec_constant
+  spv.func @variable_init_spec_constant() -> () "None" {
+    %0 = spv.mlir.referenceof @sc : i32
+    // CHECK: spv.Variable init(%0) : !spv.ptr<i32, Function>
+    %1 = spv.Variable init(%0) : !spv.ptr<i32, Function>
+    spv.Return
+  }
+}
+
+// -----
+
+func @variable_bind() -> () {
+  // expected-error @+1 {{cannot have 'descriptor_set' attribute (only allowed in spv.globalVariable)}}
+  %0 = spv.Variable bind(1, 2) : !spv.ptr<f32, Function>
+  return
+}
+
+// -----
+
+func @variable_init_bind() -> () {
+  %0 = spv.constant 4.0 : f32
+  // expected-error @+1 {{cannot have 'binding' attribute (only allowed in spv.globalVariable)}}
+  %1 = spv.Variable init(%0) {binding = 5 : i32} : !spv.ptr<f32, Function>
+  return
+}
+
+// -----
+
+func @variable_builtin() -> () {
+  // expected-error @+1 {{cannot have 'built_in' attribute (only allowed in spv.globalVariable)}}
+  %1 = spv.Variable built_in("GlobalInvocationID") : !spv.ptr<vector<3xi32>, Function>
+  return
+}
+
+// -----
+
+func @expect_ptr_result_type(%arg0: f32) -> () {
+  // expected-error @+1 {{expected spv.ptr type}}
+  %0 = spv.Variable : f32
+  return
+}
+
+// -----
+
+func @variable_init(%arg0: f32) -> () {
+  // expected-error @+1 {{op initializer must be the result of a constant or spv.globalVariable op}}
+  %0 = spv.Variable init(%arg0) : !spv.ptr<f32, Function>
+  return
+}
+
+// -----
+
+func @cannot_be_generic_storage_class(%arg0: f32) -> () {
+  // expected-error @+1 {{op can only be used to model function-level variables. Use spv.globalVariable for module-level variables}}
+  %0 = spv.Variable : !spv.ptr<f32, Generic>
+  return
+}
+
+// -----
+
+func @copy_memory_incompatible_ptrs() {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  %1 = spv.Variable : !spv.ptr<i32, Function>
+  // expected-error @+1 {{both operands must be pointers to the same type}}
+  "spv.CopyMemory"(%0, %1) {} : (!spv.ptr<f32, Function>, !spv.ptr<i32, Function>) -> ()
+  spv.Return
+}
+
+// -----
+
+func @copy_memory_invalid_maa() {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  %1 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{missing alignment value}}
+  "spv.CopyMemory"(%0, %1) {memory_access=0x0002 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
+  spv.Return
+}
+
+// -----
+
+func @copy_memory_invalid_source_maa() {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  %1 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{invalid alignment specification with non-aligned memory access specification}}
+  "spv.CopyMemory"(%0, %1) {source_memory_access=0x0001 : i32, memory_access=0x0002 : i32, source_alignment=8 : i32, alignment=4 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
+  spv.Return
+}
+
+// -----
+
+func @copy_memory_invalid_source_maa2() {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  %1 = spv.Variable : !spv.ptr<f32, Function>
+  // expected-error @+1 {{missing alignment value}}
+  "spv.CopyMemory"(%0, %1) {source_memory_access=0x0002 : i32, memory_access=0x0002 : i32, alignment=4 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
+  spv.Return
+}
+
+// -----
+
+func @copy_memory_print_maa() {
+  %0 = spv.Variable : !spv.ptr<f32, Function>
+  %1 = spv.Variable : !spv.ptr<f32, Function>
+
+  // CHECK: spv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Volatile"] : f32
+  "spv.CopyMemory"(%0, %1) {memory_access=0x0001 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
+
+  // CHECK: spv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Aligned", 4] : f32
+  "spv.CopyMemory"(%0, %1) {memory_access=0x0002 : i32, alignment=4 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
+
+  // CHECK: spv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Aligned", 4], ["Volatile"] : f32
+  "spv.CopyMemory"(%0, %1) {source_memory_access=0x0001 : i32, memory_access=0x0002 : i32, alignment=4 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
+
+  // CHECK: spv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Aligned", 4], ["Aligned", 8] : f32
+  "spv.CopyMemory"(%0, %1) {source_memory_access=0x0002 : i32, memory_access=0x0002 : i32, source_alignment=8 : i32, alignment=4 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
+
+  spv.Return
+}

diff  --git a/mlir/test/Dialect/SPIRV/IR/misc-ops.mlir b/mlir/test/Dialect/SPIRV/IR/misc-ops.mlir
new file mode 100644
index 000000000000..537dccee0b44
--- /dev/null
+++ b/mlir/test/Dialect/SPIRV/IR/misc-ops.mlir
@@ -0,0 +1,29 @@
+// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
+
+//===----------------------------------------------------------------------===//
+// spv.undef
+//===----------------------------------------------------------------------===//
+
+func @undef() -> () {
+  // CHECK: %{{.*}} = spv.undef : f32
+  %0 = spv.undef : f32
+  // CHECK: %{{.*}} = spv.undef : vector<4xf32>
+  %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
+}

diff  --git a/mlir/test/Dialect/SPIRV/IR/ops.mlir b/mlir/test/Dialect/SPIRV/IR/ops.mlir
deleted file mode 100644
index 92cca0122cf7..000000000000
--- a/mlir/test/Dialect/SPIRV/IR/ops.mlir
+++ /dev/null
@@ -1,1355 +0,0 @@
-// RUN: mlir-opt -allow-unregistered-dialect -split-input-file -verify-diagnostics %s | FileCheck %s
-
-//===----------------------------------------------------------------------===//
-// spv.AccessChain
-//===----------------------------------------------------------------------===//
-
-func @access_chain_struct() -> () {
-  %0 = spv.constant 1: i32
-  %1 = spv.Variable : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>
-  // CHECK: spv.AccessChain {{.*}}[{{.*}}, {{.*}}] : !spv.ptr<!spv.struct<(f32, !spv.array<4 x f32>)>, Function>
-  %2 = spv.AccessChain %1[%0, %0] : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>, i32, i32
-  return
-}
-
-func @access_chain_1D_array(%arg0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.array<4xf32>, Function>
-  // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.array<4 x f32>, Function>
-  %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.array<4xf32>, Function>, i32
-  return
-}
-
-func @access_chain_2D_array_1(%arg0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
-  // CHECK: spv.AccessChain {{.*}}[{{.*}}, {{.*}}] : !spv.ptr<!spv.array<4 x !spv.array<4 x f32>>, Function>
-  %1 = spv.AccessChain %0[%arg0, %arg0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32, i32
-  %2 = spv.Load "Function" %1 ["Volatile"] : f32
-  return
-}
-
-func @access_chain_2D_array_2(%arg0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
-  // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.array<4 x !spv.array<4 x f32>>, Function>
-  %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32
-  %2 = spv.Load "Function" %1 ["Volatile"] : !spv.array<4xf32>
-  return
-}
-
-func @access_chain_rtarray(%arg0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.rtarray<f32>, Function>
-  // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.rtarray<f32>, Function>
-  %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.rtarray<f32>, Function>, i32
-  %2 = spv.Load "Function" %1 ["Volatile"] : f32
-  return
-}
-
-// -----
-
-func @access_chain_non_composite() -> () {
-  %0 = spv.constant 1: i32
-  %1 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{cannot extract from non-composite type 'f32' with index 0}}
-  %2 = spv.AccessChain %1[%0] : !spv.ptr<f32, Function>, i32
-  return
-}
-
-// -----
-
-func @access_chain_no_indices(%index0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
-  // expected-error @+1 {{expected at least one index}}
-  %1 = spv.AccessChain %0[] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32
-  return
-}
-
-// -----
-
-func @access_chain_missing_comma(%index0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
-  // expected-error @+1 {{expected ','}}
-  %1 = spv.AccessChain %0[%index0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function> i32
-  return
-}
-
-// -----
-
-func @access_chain_invalid_indices_types_count(%index0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
-  // expected-error @+1 {{'spv.AccessChain' op indices types' count must be equal to indices info count}}
-  %1 = spv.AccessChain %0[%index0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32, i32
-  return
-}
-
-// -----
-
-func @access_chain_missing_indices_type(%index0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
-  // expected-error @+1 {{'spv.AccessChain' op indices types' count must be equal to indices info count}}
-  %1 = spv.AccessChain %0[%index0, %index0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32
-  return
-}
-
-// -----
-
-func @access_chain_invalid_type(%index0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
-  %1 = spv.Load "Function" %0 ["Volatile"] : !spv.array<4x!spv.array<4xf32>>
-  // expected-error @+1 {{expected a pointer to composite type, but provided '!spv.array<4 x !spv.array<4 x f32>>'}}
-  %2 = spv.AccessChain %1[%index0] : !spv.array<4x!spv.array<4xf32>>, i32
-  return
-}
-
-// -----
-
-func @access_chain_invalid_index_1(%index0 : i32) -> () {
-   %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
-  // expected-error @+1 {{expected SSA operand}}
-  %1 = spv.AccessChain %0[%index, 4] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32, i32
-  return
-}
-
-// -----
-
-func @access_chain_invalid_index_2(%index0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>
-  // expected-error @+1 {{index must be an integer spv.constant to access element of spv.struct}}
-  %1 = spv.AccessChain %0[%index0, %index0] : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>, i32, i32
-  return
-}
-
-// -----
-
-func @access_chain_invalid_constant_type_1() -> () {
-  %0 = std.constant 1: i32
-  %1 = spv.Variable : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>
-  // expected-error @+1 {{index must be an integer spv.constant to access element of spv.struct, but provided std.constant}}
-  %2 = spv.AccessChain %1[%0, %0] : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>, i32, i32
-  return
-}
-
-// -----
-
-func @access_chain_out_of_bounds() -> () {
-  %index0 = "spv.constant"() { value = 12: i32} : () -> i32
-  %0 = spv.Variable : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>
-  // expected-error @+1 {{'spv.AccessChain' op index 12 out of bounds for '!spv.struct<(f32, !spv.array<4 x f32>)>'}}
-  %1 = spv.AccessChain %0[%index0, %index0] : !spv.ptr<!spv.struct<(f32, !spv.array<4xf32>)>, Function>, i32, i32
-  return
-}
-
-// -----
-
-func @access_chain_invalid_accessing_type(%index0 : i32) -> () {
-  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
-  // expected-error @+1 {{cannot extract from non-composite type 'f32' with index 0}}
-  %1 = spv.AccessChain %0[%index, %index0, %index0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32, i32, i32
-  return
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.Bitcast
-//===----------------------------------------------------------------------===//
-
-func @cast1(%arg0 : f32) {
-  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : f32 to i32
-  %0 = spv.Bitcast %arg0 : f32 to i32
-  return
-}
-
-func @cast2(%arg0 : vector<2xf32>) {
-  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<2xf32> to vector<2xi32>
-  %0 = spv.Bitcast %arg0 : vector<2xf32> to vector<2xi32>
-  return
-}
-
-func @cast3(%arg0 : vector<2xf32>) {
-  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<2xf32> to i64
-  %0 = spv.Bitcast %arg0 : vector<2xf32> to i64
-  return
-}
-
-func @cast4(%arg0 : !spv.ptr<f32, Function>) {
-  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : !spv.ptr<f32, Function> to !spv.ptr<i32, Function>
-  %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to !spv.ptr<i32, Function>
-  return
-}
-
-func @cast5(%arg0 : !spv.ptr<f32, Function>) {
-  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : !spv.ptr<f32, Function> to !spv.ptr<vector<2xi32>, Function>
-  %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to !spv.ptr<vector<2xi32>, Function>
-  return
-}
-
-func @cast6(%arg0 : vector<4xf32>) {
-  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<4xf32> to vector<2xi64>
-  %0 = spv.Bitcast %arg0 : vector<4xf32> to vector<2xi64>
-  return
-}
-
-// -----
-
-func @cast1(%arg0 : f32) {
-  // expected-error @+1 {{result type must be 
diff erent from operand type}}
-  %0 = spv.Bitcast %arg0 : f32 to f32
-  return
-}
-
-// -----
-
-func @cast1(%arg0 : f32) {
-  // expected-error @+1 {{mismatch in result type bitwidth 64 and operand type bitwidth 32}}
-  %0 = spv.Bitcast %arg0 : f32 to i64
-  return
-}
-
-// -----
-
-func @cast1(%arg0 : vector<2xf32>) {
-  // expected-error @+1 {{mismatch in result type bitwidth 96 and operand type bitwidth 64}}
-  %0 = spv.Bitcast %arg0 : vector<2xf32> to vector<3xf32>
-  return
-}
-
-// -----
-
-func @cast3(%arg0 : !spv.ptr<f32, Function>) {
-  // expected-error @+1 {{unhandled bit cast conversion from pointer type to non-pointer type}}
-  %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to i64
-  return
-}
-
-// -----
-
-func @cast3(%arg0 : i64) {
-  // expected-error @+1 {{unhandled bit cast conversion from non-pointer type to pointer type}}
-  %0 = spv.Bitcast %arg0 : i64 to !spv.ptr<f32, Function>
-  return
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.BitCount
-//===----------------------------------------------------------------------===//
-
-func @bitcount(%arg: i32) -> i32 {
-  // CHECK: spv.BitCount {{%.*}} : i32
-  %0 = spv.BitCount %arg : i32
-  spv.ReturnValue %0 : i32
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.BitFieldInsert
-//===----------------------------------------------------------------------===//
-
-func @bit_field_insert_vec(%base: vector<3xi32>, %insert: vector<3xi32>, %offset: i32, %count: i16) -> vector<3xi32> {
-  // CHECK: {{%.*}} = spv.BitFieldInsert {{%.*}}, {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i32, i16
-  %0 = spv.BitFieldInsert %base, %insert, %offset, %count : vector<3xi32>, i32, i16
-  spv.ReturnValue %0 : vector<3xi32>
-}
-
-// -----
-
-func @bit_field_insert_invalid_insert_type(%base: vector<3xi32>, %insert: vector<2xi32>, %offset: i32, %count: i16) -> vector<3xi32> {
-  // expected-error @+1 {{all of {base, insert, result} have same type}}
-  %0 = "spv.BitFieldInsert" (%base, %insert, %offset, %count) : (vector<3xi32>, vector<2xi32>, i32, i16) -> vector<3xi32>
-  spv.ReturnValue %0 : vector<3xi32>
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.BitFieldSExtract
-//===----------------------------------------------------------------------===//
-
-func @bit_field_s_extract_vec(%base: vector<3xi32>, %offset: i8, %count: i8) -> vector<3xi32> {
-  // CHECK: {{%.*}} = spv.BitFieldSExtract {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i8, i8
-  %0 = spv.BitFieldSExtract %base, %offset, %count : vector<3xi32>, i8, i8
-  spv.ReturnValue %0 : vector<3xi32>
-}
-
-//===----------------------------------------------------------------------===//
-// spv.BitFieldUExtract
-//===----------------------------------------------------------------------===//
-
-func @bit_field_u_extract_vec(%base: vector<3xi32>, %offset: i8, %count: i8) -> vector<3xi32> {
-  // CHECK: {{%.*}} = spv.BitFieldUExtract {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i8, i8
-  %0 = spv.BitFieldUExtract %base, %offset, %count : vector<3xi32>, i8, i8
-  spv.ReturnValue %0 : vector<3xi32>
-}
-
-// -----
-
-func @bit_field_u_extract_invalid_result_type(%base: vector<3xi32>, %offset: i32, %count: i16) -> vector<4xi32> {
-  // expected-error @+1 {{failed to verify that all of {base, result} have same type}}
-  %0 = "spv.BitFieldUExtract" (%base, %offset, %count) : (vector<3xi32>, i32, i16) -> vector<4xi32>
-  spv.ReturnValue %0 : vector<4xi32>
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.BitReverse
-//===----------------------------------------------------------------------===//
-
-func @bitreverse(%arg: i32) -> i32 {
-  // CHECK: spv.BitReverse {{%.*}} : i32
-  %0 = spv.BitReverse %arg : i32
-  spv.ReturnValue %0 : i32
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.ControlBarrier
-//===----------------------------------------------------------------------===//
-
-func @control_barrier_0() -> () {
-  // CHECK:  spv.ControlBarrier "Workgroup", "Device", "Acquire|UniformMemory"
-  spv.ControlBarrier "Workgroup", "Device", "Acquire|UniformMemory"
-  return
-}
-
-// -----
-
-func @control_barrier_1() -> () {
-  // expected-error @+1 {{invalid execution_scope attribute specification: "Something"}}
-  spv.ControlBarrier "Something", "Device", "Acquire|UniformMemory"
-  return
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.ConvertFToS
-//===----------------------------------------------------------------------===//
-
-func @convert_f_to_s_scalar(%arg0 : f32) -> i32 {
-  // CHECK: {{%.*}} = spv.ConvertFToS {{%.*}} : f32 to i32
-  %0 = spv.ConvertFToS %arg0 : f32 to i32
-  spv.ReturnValue %0 : i32
-}
-
-// -----
-
-func @convert_f64_to_s32_scalar(%arg0 : f64) -> i32 {
-  // CHECK: {{%.*}} = spv.ConvertFToS {{%.*}} : f64 to i32
-  %0 = spv.ConvertFToS %arg0 : f64 to i32
-  spv.ReturnValue %0 : i32
-}
-
-// -----
-
-func @convert_f_to_s_vector(%arg0 : vector<3xf32>) -> vector<3xi32> {
-  // CHECK: {{%.*}} = spv.ConvertFToS {{%.*}} : vector<3xf32> to vector<3xi32>
-  %0 = spv.ConvertFToS %arg0 : vector<3xf32> to vector<3xi32>
-  spv.ReturnValue %0 : vector<3xi32>
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.ConvertFToU
-//===----------------------------------------------------------------------===//
-
-func @convert_f_to_u_scalar(%arg0 : f32) -> i32 {
-  // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : f32 to i32
-  %0 = spv.ConvertFToU %arg0 : f32 to i32
-  spv.ReturnValue %0 : i32
-}
-
-// -----
-
-func @convert_f64_to_u32_scalar(%arg0 : f64) -> i32 {
-  // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : f64 to i32
-  %0 = spv.ConvertFToU %arg0 : f64 to i32
-  spv.ReturnValue %0 : i32
-}
-
-// -----
-
-func @convert_f_to_u_vector(%arg0 : vector<3xf32>) -> vector<3xi32> {
-  // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : vector<3xf32> to vector<3xi32>
-  %0 = spv.ConvertFToU %arg0 : vector<3xf32> to vector<3xi32>
-  spv.ReturnValue %0 : vector<3xi32>
-}
-
-// -----
-
-func @convert_f_to_u_coopmatrix(%arg0 : !spv.coopmatrix<8x16xf32, Subgroup>) {
-  // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : !spv.coopmatrix<8x16xf32, Subgroup> to !spv.coopmatrix<8x16xi32, Subgroup>
-  %0 = spv.ConvertFToU %arg0 : !spv.coopmatrix<8x16xf32, Subgroup> to !spv.coopmatrix<8x16xi32, Subgroup>
-  spv.Return
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.ConvertSToF
-//===----------------------------------------------------------------------===//
-
-func @convert_s_to_f_scalar(%arg0 : i32) -> f32 {
-  // CHECK: {{%.*}} = spv.ConvertSToF {{%.*}} : i32 to f32
-  %0 = spv.ConvertSToF %arg0 : i32 to f32
-  spv.ReturnValue %0 : f32
-}
-
-// -----
-
-func @convert_s64_to_f32_scalar(%arg0 : i64) -> f32 {
-  // CHECK: {{%.*}} = spv.ConvertSToF {{%.*}} : i64 to f32
-  %0 = spv.ConvertSToF %arg0 : i64 to f32
-  spv.ReturnValue %0 : f32
-}
-
-// -----
-
-func @convert_s_to_f_vector(%arg0 : vector<3xi32>) -> vector<3xf32> {
-  // CHECK: {{%.*}} = spv.ConvertSToF {{%.*}} : vector<3xi32> to vector<3xf32>
-  %0 = spv.ConvertSToF %arg0 : vector<3xi32> to vector<3xf32>
-  spv.ReturnValue %0 : vector<3xf32>
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.ConvertUToF
-//===----------------------------------------------------------------------===//
-
-func @convert_u_to_f_scalar(%arg0 : i32) -> f32 {
-  // CHECK: {{%.*}} = spv.ConvertUToF {{%.*}} : i32 to f32
-  %0 = spv.ConvertUToF %arg0 : i32 to f32
-  spv.ReturnValue %0 : f32
-}
-
-// -----
-
-func @convert_u64_to_f32_scalar(%arg0 : i64) -> f32 {
-  // CHECK: {{%.*}} = spv.ConvertUToF {{%.*}} : i64 to f32
-  %0 = spv.ConvertUToF %arg0 : i64 to f32
-  spv.ReturnValue %0 : f32
-}
-
-// -----
-
-func @convert_u_to_f_vector(%arg0 : vector<3xi32>) -> vector<3xf32> {
-  // CHECK: {{%.*}} = spv.ConvertUToF {{%.*}} : vector<3xi32> to vector<3xf32>
-  %0 = spv.ConvertUToF %arg0 : vector<3xi32> to vector<3xf32>
-  spv.ReturnValue %0 : vector<3xf32>
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.FConvert
-//===----------------------------------------------------------------------===//
-
-func @f_convert_scalar(%arg0 : f32) -> f64 {
-  // CHECK: {{%.*}} = spv.FConvert {{%.*}} : f32 to f64
-  %0 = spv.FConvert %arg0 : f32 to f64
-  spv.ReturnValue %0 : f64
-}
-
-// -----
-
-func @f_convert_vector(%arg0 : vector<3xf32>) -> vector<3xf64> {
-  // CHECK: {{%.*}} = spv.FConvert {{%.*}} : vector<3xf32> to vector<3xf64>
-  %0 = spv.FConvert %arg0 : vector<3xf32> to vector<3xf64>
-  spv.ReturnValue %0 : vector<3xf64>
-}
-
-// -----
-
-func @f_convert_coop_matrix(%arg0 : !spv.coopmatrix<8x16xf32, Subgroup>) {
-  // CHECK: {{%.*}} = spv.FConvert {{%.*}} : !spv.coopmatrix<8x16xf32, Subgroup> to !spv.coopmatrix<8x16xf64, Subgroup>
-  %0 = spv.FConvert %arg0 : !spv.coopmatrix<8x16xf32, Subgroup> to !spv.coopmatrix<8x16xf64, Subgroup>
-  spv.Return
-}
-
-// -----
-
-func @f_convert_vector(%arg0 : f32) -> f32 {
-  // expected-error @+1 {{expected the 
diff erent bit widths for operand type and result type, but provided 'f32' and 'f32'}}
-  %0 = spv.FConvert %arg0 : f32 to f32
-  spv.ReturnValue %0 : f32
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.SConvert
-//===----------------------------------------------------------------------===//
-
-func @s_convert_scalar(%arg0 : i32) -> i64 {
-  // CHECK: {{%.*}} = spv.SConvert {{%.*}} : i32 to i64
-  %0 = spv.SConvert %arg0 : i32 to i64
-  spv.ReturnValue %0 : i64
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.UConvert
-//===----------------------------------------------------------------------===//
-
-func @u_convert_scalar(%arg0 : i32) -> i64 {
-  // CHECK: {{%.*}} = spv.UConvert {{%.*}} : i32 to i64
-  %0 = spv.UConvert %arg0 : i32 to i64
-  spv.ReturnValue %0 : i64
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.ExecutionMode
-//===----------------------------------------------------------------------===//
-
-spv.module Logical GLSL450 {
-   spv.func @do_nothing() -> () "None" {
-     spv.Return
-   }
-   spv.EntryPoint "GLCompute" @do_nothing
-   // CHECK: spv.ExecutionMode {{@.*}} "ContractionOff"
-   spv.ExecutionMode @do_nothing "ContractionOff"
-}
-
-spv.module Logical GLSL450 {
-   spv.func @do_nothing() -> () "None" {
-     spv.Return
-   }
-   spv.EntryPoint "GLCompute" @do_nothing
-   // CHECK: spv.ExecutionMode {{@.*}} "LocalSizeHint", 3, 4, 5
-   spv.ExecutionMode @do_nothing "LocalSizeHint", 3, 4, 5
-}
-
-// -----
-
-spv.module Logical GLSL450 {
-   spv.func @do_nothing() -> () "None" {
-     spv.Return
-   }
-   spv.EntryPoint "GLCompute" @do_nothing
-   // expected-error @+1 {{custom op 'spv.ExecutionMode' invalid execution_mode attribute specification: "GLCompute"}}
-   spv.ExecutionMode @do_nothing "GLCompute", 3, 4, 5
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.LoadOp
-//===----------------------------------------------------------------------===//
-
-// CHECK-LABEL: @simple_load
-func @simple_load() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Load "Function" %{{.*}} : f32
-  %1 = spv.Load "Function" %0 : f32
-  return
-}
-
-// CHECK-LABEL: @load_none_access
-func @load_none_access() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Load "Function" %{{.*}} ["None"] : f32
-  %1 = spv.Load "Function" %0 ["None"] : f32
-  return
-}
-
-// CHECK-LABEL: @volatile_load
-func @volatile_load() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Load "Function" %{{.*}} ["Volatile"] : f32
-  %1 = spv.Load "Function" %0 ["Volatile"] : f32
-  return
-}
-
-// CHECK-LABEL: @aligned_load
-func @aligned_load() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Load "Function" %{{.*}} ["Aligned", 4] : f32
-  %1 = spv.Load "Function" %0 ["Aligned", 4] : f32
-  return
-}
-
-// CHECK-LABEL: @volatile_aligned_load
-func @volatile_aligned_load() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Load "Function" %{{.*}} ["Volatile|Aligned", 4] : f32
-  %1 = spv.Load "Function" %0 ["Volatile|Aligned", 4] : f32
-  return
-}
-
-// -----
-
-// CHECK-LABEL: load_none_access
-func @load_none_access() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Load
-  // CHECK-SAME: ["None"]
-  %1 = "spv.Load"(%0) {memory_access = 0 : i32} : (!spv.ptr<f32, Function>) -> (f32)
-  return
-}
-
-// CHECK-LABEL: volatile_load
-func @volatile_load() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Load
-  // CHECK-SAME: ["Volatile"]
-  %1 = "spv.Load"(%0) {memory_access = 1 : i32} : (!spv.ptr<f32, Function>) -> (f32)
-  return
-}
-
-// CHECK-LABEL: aligned_load
-func @aligned_load() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Load
-  // CHECK-SAME: ["Aligned", 4]
-  %1 = "spv.Load"(%0) {memory_access = 2 : i32, alignment = 4 : i32} : (!spv.ptr<f32, Function>) -> (f32)
-  return
-}
-
-// CHECK-LABEL: volatile_aligned_load
-func @volatile_aligned_load() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Load
-  // CHECK-SAME: ["Volatile|Aligned", 4]
-  %1 = "spv.Load"(%0) {memory_access = 3 : i32, alignment = 4 : i32} : (!spv.ptr<f32, Function>) -> (f32)
-  return
-}
-
-// -----
-
-func @simple_load_missing_storageclass() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected non-function type}}
-  %1 = spv.Load %0 : f32
-  return
-}
-
-// -----
-
-func @simple_load_missing_operand() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected SSA operand}}
-  %1 = spv.Load "Function" : f32
-  return
-}
-
-// -----
-
-func @simple_load_missing_rettype() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+2 {{expected ':'}}
-  %1 = spv.Load "Function" %0
-  return
-}
-
-// -----
-
-func @volatile_load_missing_lbrace() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ':'}}
-  %1 = spv.Load "Function" %0 "Volatile"] : f32
-  return
-}
-
-// -----
-
-func @volatile_load_missing_rbrace() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ']'}}
-  %1 = spv.Load "Function" %0 ["Volatile"} : f32
-  return
-}
-
-// -----
-
-func @aligned_load_missing_alignment() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ','}}
-  %1 = spv.Load "Function" %0 ["Aligned"] : f32
-  return
-}
-
-// -----
-
-func @aligned_load_missing_comma() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ','}}
-  %1 = spv.Load "Function" %0 ["Aligned" 4] : f32
-  return
-}
-
-// -----
-
-func @load_incorrect_attributes() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ']'}}
-  %1 = spv.Load "Function" %0 ["Volatile", 4] : f32
-  return
-}
-
-// -----
-
-func @load_unknown_memory_access() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{custom op 'spv.Load' invalid memory_access attribute specification: "Something"}}
-  %1 = spv.Load "Function" %0 ["Something"] : f32
-  return
-}
-
-// -----
-
-func @load_unknown_memory_access() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{custom op 'spv.Load' invalid memory_access attribute specification: "Volatile|Something"}}
-  %1 = spv.Load "Function" %0 ["Volatile|Something"] : f32
-  return
-}
-
-// -----
-
-func @load_unknown_memory_access() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{failed to satisfy constraint: valid SPIR-V MemoryAccess}}
-  %1 = "spv.Load"(%0) {memory_access = 0x80000000 : i32} : (!spv.ptr<f32, Function>) -> (f32)
-  return
-}
-
-// -----
-
-func @aligned_load_incorrect_attributes() -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ']'}}
-  %1 = spv.Load "Function" %0 ["Aligned", 4, 23] : f32
-  return
-}
-
-// -----
-
-spv.module Logical GLSL450 {
-  spv.globalVariable @var0 : !spv.ptr<f32, Input>
-  // CHECK_LABEL: @simple_load
-  spv.func @simple_load() -> () "None" {
-    // CHECK: spv.Load "Input" {{%.*}} : f32
-    %0 = spv.mlir.addressof @var0 : !spv.ptr<f32, Input>
-    %1 = spv.Load "Input" %0 : f32
-    spv.Return
-  }
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.LogicalAnd
-//===----------------------------------------------------------------------===//
-
-func @logicalBinary(%arg0 : i1, %arg1 : i1, %arg2 : i1)
-{
-  // CHECK: [[TMP:%.*]] = spv.LogicalAnd {{%.*}}, {{%.*}} : i1
-  %0 = spv.LogicalAnd %arg0, %arg1 : i1
-  // CHECK: {{%.*}} = spv.LogicalAnd [[TMP]], {{%.*}} : i1
-  %1 = spv.LogicalAnd %0, %arg2 : i1
-  return
-}
-
-func @logicalBinary2(%arg0 : vector<4xi1>, %arg1 : vector<4xi1>)
-{
-  // CHECK: {{%.*}} = spv.LogicalAnd {{%.*}}, {{%.*}} : vector<4xi1>
-  %0 = spv.LogicalAnd %arg0, %arg1 : vector<4xi1>
-  return
-}
-
-// -----
-
-func @logicalBinary(%arg0 : i1, %arg1 : i1)
-{
-  // expected-error @+2 {{expected ':'}}
-  %0 = spv.LogicalAnd %arg0, %arg1
-  return
-}
-
-// -----
-
-func @logicalBinary(%arg0 : i1, %arg1 : i1)
-{
-  // expected-error @+2 {{expected non-function type}}
-  %0 = spv.LogicalAnd %arg0, %arg1 :
-  return
-}
-
-// -----
-
-func @logicalBinary(%arg0 : i1, %arg1 : i1)
-{
-  // expected-error @+1 {{custom op 'spv.LogicalAnd' expected 2 operands}}
-  %0 = spv.LogicalAnd %arg0 : i1
-  return
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.LogicalNot
-//===----------------------------------------------------------------------===//
-
-func @logicalUnary(%arg0 : i1, %arg1 : i1)
-{
-  // CHECK: [[TMP:%.*]] = spv.LogicalNot {{%.*}} : i1
-  %0 = spv.LogicalNot %arg0 : i1
-  // CHECK: {{%.*}} = spv.LogicalNot [[TMP]] : i1
-  %1 = spv.LogicalNot %0 : i1
-  return
-}
-
-func @logicalUnary2(%arg0 : vector<4xi1>)
-{
-  // CHECK: {{%.*}} = spv.LogicalNot {{%.*}} : vector<4xi1>
-  %0 = spv.LogicalNot %arg0 : vector<4xi1>
-  return
-}
-
-// -----
-
-func @logicalUnary(%arg0 : i1)
-{
-  // expected-error @+2 {{expected ':'}}
-  %0 = spv.LogicalNot %arg0
-  return
-}
-
-// -----
-
-func @logicalUnary(%arg0 : i1)
-{
-  // expected-error @+2 {{expected non-function type}}
-  %0 = spv.LogicalNot %arg0 :
-  return
-}
-
-// -----
-
-func @logicalUnary(%arg0 : i1)
-{
-  // expected-error @+1 {{expected SSA operand}}
-  %0 = spv.LogicalNot : i1
-  return
-}
-
-// -----
-
-func @logicalUnary(%arg0 : i32)
-{
-  // expected-error @+1 {{operand #0 must be bool or vector of bool values of length 2/3/4/8/16, but got 'i32'}}
-  %0 = spv.LogicalNot %arg0 : i32
-  return
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.MemoryBarrier
-//===----------------------------------------------------------------------===//
-
-func @memory_barrier_0() -> () {
-  // CHECK: spv.MemoryBarrier "Device", "Acquire|UniformMemory"
-  spv.MemoryBarrier "Device", "Acquire|UniformMemory"
-  return
-}
-
-// -----
-
-func @memory_barrier_1() -> () {
-  // CHECK: spv.MemoryBarrier "Workgroup", "Acquire"
-  spv.MemoryBarrier "Workgroup", "Acquire"
-  return
-}
-
-// -----
-
-func @memory_barrier_2() -> () {
- // expected-error @+1 {{expected at most one of these four memory constraints to be set: `Acquire`, `Release`,`AcquireRelease` or `SequentiallyConsistent`}}
-  spv.MemoryBarrier "Device", "Acquire|Release"
-  return
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.Not
-//===----------------------------------------------------------------------===//
-
-func @not(%arg: i32) -> i32 {
-  // CHECK: spv.Not {{%.*}} : i32
-  %0 = spv.Not %arg : i32
-  spv.ReturnValue %0 : i32
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.SelectOp
-//===----------------------------------------------------------------------===//
-
-func @select_op_bool(%arg0: i1) -> () {
-  %0 = spv.constant true
-  %1 = spv.constant false
-  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, i1
-  %2 = spv.Select %arg0, %0, %1 : i1, i1
-  return
-}
-
-func @select_op_int(%arg0: i1) -> () {
-  %0 = spv.constant 2 : i32
-  %1 = spv.constant 3 : i32
-  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, i32
-  %2 = spv.Select %arg0, %0, %1 : i1, i32
-  return
-}
-
-func @select_op_float(%arg0: i1) -> () {
-  %0 = spv.constant 2.0 : f32
-  %1 = spv.constant 3.0 : f32
-  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, f32
-  %2 = spv.Select %arg0, %0, %1 : i1, f32
-  return
-}
-
-func @select_op_ptr(%arg0: i1) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  %1 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, !spv.ptr<f32, Function>
-  %2 = spv.Select %arg0, %0, %1 : i1, !spv.ptr<f32, Function>
-  return
-}
-
-func @select_op_vec(%arg0: i1) -> () {
-  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
-  %1 = spv.constant dense<[5.0, 6.0, 7.0]> : vector<3xf32>
-  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, vector<3xf32>
-  %2 = spv.Select %arg0, %0, %1 : i1, vector<3xf32>
-  return
-}
-
-func @select_op_vec_condn_vec(%arg0: vector<3xi1>) -> () {
-  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
-  %1 = spv.constant dense<[5.0, 6.0, 7.0]> : vector<3xf32>
-  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi1>, vector<3xf32>
-  %2 = spv.Select %arg0, %0, %1 : vector<3xi1>, vector<3xf32>
-  return
-}
-
-// -----
-
-func @select_op(%arg0: i1) -> () {
-  %0 = spv.constant 2 : i32
-  %1 = spv.constant 3 : i32
-  // expected-error @+2 {{expected ','}}
-  %2 = spv.Select %arg0, %0, %1 : i1
-  return
-}
-
-// -----
-
-func @select_op(%arg1: vector<3xi1>) -> () {
-  %0 = spv.constant 2 : i32
-  %1 = spv.constant 3 : i32
-  // expected-error @+1 {{result expected to be of vector type when condition is of vector type}}
-  %2 = spv.Select %arg1, %0, %1 : vector<3xi1>, i32
-  return
-}
-
-// -----
-
-func @select_op(%arg1: vector<4xi1>) -> () {
-  %0 = spv.constant dense<[2, 3, 4]> : vector<3xi32>
-  %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32>
-  // expected-error @+1 {{result should have the same number of elements as the condition when condition is of vector type}}
-  %2 = spv.Select %arg1, %0, %1 : vector<4xi1>, vector<3xi32>
-  return
-}
-
-// -----
-
-func @select_op(%arg1: vector<4xi1>) -> () {
-  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
-  %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32>
-  // expected-error @+1 {{all of {true_value, false_value, result} have same type}}
-  %2 = "spv.Select"(%arg1, %0, %1) : (vector<4xi1>, vector<3xf32>, vector<3xi32>) -> vector<3xi32>
-  return
-}
-
-// -----
-
-func @select_op(%arg1: vector<4xi1>) -> () {
-  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
-  %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32>
-  // expected-error @+1 {{all of {true_value, false_value, result} have same type}}
-  %2 = "spv.Select"(%arg1, %1, %0) : (vector<4xi1>, vector<3xi32>, vector<3xf32>) -> vector<3xi32>
-  return
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.ShiftLeftLogical
-//===----------------------------------------------------------------------===//
-
-func @shift_left_logical(%arg0: i32, %arg1 : i16) -> i32 {
-  // CHECK: {{%.*}} = spv.ShiftLeftLogical {{%.*}}, {{%.*}} : i32, i16
-  %0 = spv.ShiftLeftLogical %arg0, %arg1: i32, i16
-  spv.ReturnValue %0 : i32
-}
-
-// -----
-
-func @shift_left_logical_invalid_result_type(%arg0: i32, %arg1 : i16) -> i16 {
-  // expected-error @+1 {{expected the same type for the first operand and result, but provided 'i32' and 'i16'}}
-  %0 = "spv.ShiftLeftLogical" (%arg0, %arg1) : (i32, i16) -> (i16)
-  spv.ReturnValue %0 : i16
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.ShiftRightArithmetic
-//===----------------------------------------------------------------------===//
-
-func @shift_right_arithmetic(%arg0: vector<4xi32>, %arg1 : vector<4xi8>) -> vector<4xi32> {
-  // CHECK: {{%.*}} = spv.ShiftRightArithmetic {{%.*}}, {{%.*}} : vector<4xi32>, vector<4xi8>
-  %0 = spv.ShiftRightArithmetic %arg0, %arg1: vector<4xi32>, vector<4xi8>
-  spv.ReturnValue %0 : vector<4xi32>
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.ShiftRightLogical
-//===----------------------------------------------------------------------===//
-
-func @shift_right_logical(%arg0: vector<2xi32>, %arg1 : vector<2xi8>) -> vector<2xi32> {
-  // CHECK: {{%.*}} = spv.ShiftRightLogical {{%.*}}, {{%.*}} : vector<2xi32>, vector<2xi8>
-  %0 = spv.ShiftRightLogical %arg0, %arg1: vector<2xi32>, vector<2xi8>
-  spv.ReturnValue %0 : vector<2xi32>
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.StoreOp
-//===----------------------------------------------------------------------===//
-
-func @simple_store(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Store  "Function" %0, %arg0 : f32
-  spv.Store  "Function" %0, %arg0 : f32
-  return
-}
-
-// CHECK_LABEL: @volatile_store
-func @volatile_store(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Store  "Function" %0, %arg0 ["Volatile"] : f32
-  spv.Store  "Function" %0, %arg0 ["Volatile"] : f32
-  return
-}
-
-// CHECK_LABEL: @aligned_store
-func @aligned_store(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // CHECK: spv.Store  "Function" %0, %arg0 ["Aligned", 4] : f32
-  spv.Store  "Function" %0, %arg0 ["Aligned", 4] : f32
-  return
-}
-
-// -----
-
-func @simple_store_missing_ptr_type(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected non-function type}}
-  spv.Store  %0, %arg0 : f32
-  return
-}
-
-// -----
-
-func @simple_store_missing_operand(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{custom op 'spv.Store' invalid operand}} : f32
-  spv.Store  "Function" , %arg0 : f32
-  return
-}
-
-// -----
-
-func @simple_store_missing_operand(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{custom op 'spv.Store' expected 2 operands}} : f32
-  spv.Store  "Function" %0 : f32
-  return
-}
-
-// -----
-
-func @volatile_store_missing_lbrace(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ':'}}
-  spv.Store  "Function" %0, %arg0 "Volatile"] : f32
-  return
-}
-
-// -----
-
-func @volatile_store_missing_rbrace(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ']'}}
-  spv.Store "Function" %0, %arg0 ["Volatile"} : f32
-  return
-}
-
-// -----
-
-func @aligned_store_missing_alignment(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ','}}
-  spv.Store  "Function" %0, %arg0 ["Aligned"] : f32
-  return
-}
-
-// -----
-
-func @aligned_store_missing_comma(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ','}}
-  spv.Store  "Function" %0, %arg0 ["Aligned" 4] : f32
-  return
-}
-
-// -----
-
-func @load_incorrect_attributes(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ']'}}
-  spv.Store  "Function" %0, %arg0 ["Volatile", 4] : f32
-  return
-}
-
-// -----
-
-func @aligned_store_incorrect_attributes(%arg0 : f32) -> () {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{expected ']'}}
-  spv.Store  "Function" %0, %arg0 ["Aligned", 4, 23] : f32
-  return
-}
-
-// -----
-
-spv.module Logical GLSL450 {
-  spv.globalVariable @var0 : !spv.ptr<f32, Input>
-  spv.func @simple_store(%arg0 : f32) -> () "None" {
-    %0 = spv.mlir.addressof @var0 : !spv.ptr<f32, Input>
-    // CHECK: spv.Store  "Input" {{%.*}}, {{%.*}} : f32
-    spv.Store  "Input" %0, %arg0 : f32
-    spv.Return
-  }
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// spv.SubgroupBallotKHR
-//===----------------------------------------------------------------------===//
-
-func @subgroup_ballot(%predicate: i1) -> vector<4xi32> {
-  %0 = spv.SubgroupBallotKHR %predicate: vector<4xi32>
-  return %0: vector<4xi32>
-}
-
-// -----
-
-//===----------------------------------------------------------------------===//
-// 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
-//===----------------------------------------------------------------------===//
-
-func @variable(%arg0: f32) -> () {
-  // CHECK: spv.Variable : !spv.ptr<f32, Function>
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  return
-}
-
-// -----
-
-func @variable_init_normal_constant() -> () {
-  %0 = spv.constant 4.0 : f32
-  // CHECK: spv.Variable init(%0) : !spv.ptr<f32, Function>
-  %1 = spv.Variable init(%0) : !spv.ptr<f32, Function>
-  return
-}
-
-// -----
-
-spv.module Logical GLSL450 {
-  spv.globalVariable @global : !spv.ptr<f32, Workgroup>
-  spv.func @variable_init_global_variable() -> () "None" {
-    %0 = spv.mlir.addressof @global : !spv.ptr<f32, Workgroup>
-    // CHECK: spv.Variable init({{.*}}) : !spv.ptr<!spv.ptr<f32, Workgroup>, Function>
-    %1 = spv.Variable init(%0) : !spv.ptr<!spv.ptr<f32, Workgroup>, Function>
-    spv.Return
-  }
-}
-
-// -----
-
-spv.module Logical GLSL450 {
-  spv.specConstant @sc = 42 : i32
-  // CHECK-LABEL: @variable_init_spec_constant
-  spv.func @variable_init_spec_constant() -> () "None" {
-    %0 = spv.mlir.referenceof @sc : i32
-    // CHECK: spv.Variable init(%0) : !spv.ptr<i32, Function>
-    %1 = spv.Variable init(%0) : !spv.ptr<i32, Function>
-    spv.Return
-  }
-}
-
-// -----
-
-func @variable_bind() -> () {
-  // expected-error @+1 {{cannot have 'descriptor_set' attribute (only allowed in spv.globalVariable)}}
-  %0 = spv.Variable bind(1, 2) : !spv.ptr<f32, Function>
-  return
-}
-
-// -----
-
-func @variable_init_bind() -> () {
-  %0 = spv.constant 4.0 : f32
-  // expected-error @+1 {{cannot have 'binding' attribute (only allowed in spv.globalVariable)}}
-  %1 = spv.Variable init(%0) {binding = 5 : i32} : !spv.ptr<f32, Function>
-  return
-}
-
-// -----
-
-func @variable_builtin() -> () {
-  // expected-error @+1 {{cannot have 'built_in' attribute (only allowed in spv.globalVariable)}}
-  %1 = spv.Variable built_in("GlobalInvocationID") : !spv.ptr<vector<3xi32>, Function>
-  return
-}
-
-// -----
-
-func @expect_ptr_result_type(%arg0: f32) -> () {
-  // expected-error @+1 {{expected spv.ptr type}}
-  %0 = spv.Variable : f32
-  return
-}
-
-// -----
-
-func @variable_init(%arg0: f32) -> () {
-  // expected-error @+1 {{op initializer must be the result of a constant or spv.globalVariable op}}
-  %0 = spv.Variable init(%arg0) : !spv.ptr<f32, Function>
-  return
-}
-
-// -----
-
-func @cannot_be_generic_storage_class(%arg0: f32) -> () {
-  // expected-error @+1 {{op can only be used to model function-level variables. Use spv.globalVariable for module-level variables}}
-  %0 = spv.Variable : !spv.ptr<f32, Generic>
-  return
-}
-
-// -----
-
-func @copy_memory_incompatible_ptrs() {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  %1 = spv.Variable : !spv.ptr<i32, Function>
-  // expected-error @+1 {{both operands must be pointers to the same type}}
-  "spv.CopyMemory"(%0, %1) {} : (!spv.ptr<f32, Function>, !spv.ptr<i32, Function>) -> ()
-  spv.Return
-}
-
-// -----
-
-func @copy_memory_invalid_maa() {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  %1 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{missing alignment value}}
-  "spv.CopyMemory"(%0, %1) {memory_access=0x0002 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
-  spv.Return
-}
-
-// -----
-
-func @copy_memory_invalid_source_maa() {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  %1 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{invalid alignment specification with non-aligned memory access specification}}
-  "spv.CopyMemory"(%0, %1) {source_memory_access=0x0001 : i32, memory_access=0x0002 : i32, source_alignment=8 : i32, alignment=4 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
-  spv.Return
-}
-
-// -----
-
-func @copy_memory_invalid_source_maa2() {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  %1 = spv.Variable : !spv.ptr<f32, Function>
-  // expected-error @+1 {{missing alignment value}}
-  "spv.CopyMemory"(%0, %1) {source_memory_access=0x0002 : i32, memory_access=0x0002 : i32, alignment=4 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
-  spv.Return
-}
-
-// -----
-
-func @copy_memory_print_maa() {
-  %0 = spv.Variable : !spv.ptr<f32, Function>
-  %1 = spv.Variable : !spv.ptr<f32, Function>
-
-  // CHECK: spv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Volatile"] : f32
-  "spv.CopyMemory"(%0, %1) {memory_access=0x0001 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
-
-  // CHECK: spv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Aligned", 4] : f32
-  "spv.CopyMemory"(%0, %1) {memory_access=0x0002 : i32, alignment=4 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
-
-  // CHECK: spv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Aligned", 4], ["Volatile"] : f32
-  "spv.CopyMemory"(%0, %1) {source_memory_access=0x0001 : i32, memory_access=0x0002 : i32, alignment=4 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
-
-  // CHECK: spv.CopyMemory "Function" %{{.*}}, "Function" %{{.*}} ["Aligned", 4], ["Aligned", 8] : f32
-  "spv.CopyMemory"(%0, %1) {source_memory_access=0x0002 : i32, memory_access=0x0002 : i32, source_alignment=8 : i32, alignment=4 : i32} : (!spv.ptr<f32, Function>, !spv.ptr<f32, Function>) -> ()
-
-  spv.Return
-}

diff  --git a/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir b/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir
index c3f715f06ae2..132c4b73c937 100644
--- a/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir
@@ -213,6 +213,41 @@ spv.module Logical GLSL450 {
 
 // -----
 
+//===----------------------------------------------------------------------===//
+// spv.ExecutionMode
+//===----------------------------------------------------------------------===//
+
+spv.module Logical GLSL450 {
+   spv.func @do_nothing() -> () "None" {
+     spv.Return
+   }
+   spv.EntryPoint "GLCompute" @do_nothing
+   // CHECK: spv.ExecutionMode {{@.*}} "ContractionOff"
+   spv.ExecutionMode @do_nothing "ContractionOff"
+}
+
+spv.module Logical GLSL450 {
+   spv.func @do_nothing() -> () "None" {
+     spv.Return
+   }
+   spv.EntryPoint "GLCompute" @do_nothing
+   // CHECK: spv.ExecutionMode {{@.*}} "LocalSizeHint", 3, 4, 5
+   spv.ExecutionMode @do_nothing "LocalSizeHint", 3, 4, 5
+}
+
+// -----
+
+spv.module Logical GLSL450 {
+   spv.func @do_nothing() -> () "None" {
+     spv.Return
+   }
+   spv.EntryPoint "GLCompute" @do_nothing
+   // expected-error @+1 {{custom op 'spv.ExecutionMode' invalid execution_mode attribute specification: "GLCompute"}}
+   spv.ExecutionMode @do_nothing "GLCompute", 3, 4, 5
+}
+
+// -----
+
 //===----------------------------------------------------------------------===//
 // spv.func
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/test/Target/SPIRV/barrier.mlir b/mlir/test/Target/SPIRV/barrier-ops.mlir
similarity index 100%
rename from mlir/test/Target/SPIRV/barrier.mlir
rename to mlir/test/Target/SPIRV/barrier-ops.mlir


        


More information about the llvm-branch-commits mailing list