Add support for OpBitwiseOr, OpBitwiseXor, and OpBitwiseAnd in SPIR-V dialect.
authorHanhan Wang <hanchung@google.com>
Wed, 16 Oct 2019 01:42:10 +0000 (18:42 -0700)
committerA. Unique TensorFlower <gardener@tensorflow.org>
Wed, 16 Oct 2019 01:42:40 +0000 (18:42 -0700)
PiperOrigin-RevId: 274935374

mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
mlir/include/mlir/Dialect/SPIRV/SPIRVBitOps.td [new file with mode: 0644]
mlir/include/mlir/Dialect/SPIRV/SPIRVOps.td
mlir/test/Dialect/SPIRV/bit-ops.mlir [new file with mode: 0644]

index dfefde9..eb642c7 100644 (file)
@@ -161,6 +161,9 @@ def SPV_OC_OpFOrdLessThanEqual      : I32EnumAttrCase<"OpFOrdLessThanEqual", 188
 def SPV_OC_OpFUnordLessThanEqual    : I32EnumAttrCase<"OpFUnordLessThanEqual", 189>;
 def SPV_OC_OpFOrdGreaterThanEqual   : I32EnumAttrCase<"OpFOrdGreaterThanEqual", 190>;
 def SPV_OC_OpFUnordGreaterThanEqual : I32EnumAttrCase<"OpFUnordGreaterThanEqual", 191>;
+def SPV_OC_OpBitwiseOr              : I32EnumAttrCase<"OpBitwiseOr", 197>;
+def SPV_OC_OpBitwiseXor             : I32EnumAttrCase<"OpBitwiseXor", 198>;
+def SPV_OC_OpBitwiseAnd             : I32EnumAttrCase<"OpBitwiseAnd", 199>;
 def SPV_OC_OpControlBarrier         : I32EnumAttrCase<"OpControlBarrier", 224>;
 def SPV_OC_OpMemoryBarrier          : I32EnumAttrCase<"OpMemoryBarrier", 225>;
 def SPV_OC_OpLoopMerge              : I32EnumAttrCase<"OpLoopMerge", 246>;
@@ -201,6 +204,7 @@ def SPV_OpcodeAttr :
       SPV_OC_OpFOrdGreaterThan, SPV_OC_OpFUnordGreaterThan,
       SPV_OC_OpFOrdLessThanEqual, SPV_OC_OpFUnordLessThanEqual,
       SPV_OC_OpFOrdGreaterThanEqual, SPV_OC_OpFUnordGreaterThanEqual,
+      SPV_OC_OpBitwiseOr, SPV_OC_OpBitwiseXor, SPV_OC_OpBitwiseAnd,
       SPV_OC_OpControlBarrier, SPV_OC_OpMemoryBarrier, SPV_OC_OpLoopMerge,
       SPV_OC_OpSelectionMerge, SPV_OC_OpLabel, SPV_OC_OpBranch,
       SPV_OC_OpBranchConditional, SPV_OC_OpReturn, SPV_OC_OpReturnValue,
diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVBitOps.td b/mlir/include/mlir/Dialect/SPIRV/SPIRVBitOps.td
new file mode 100644 (file)
index 0000000..8c8e8c0
--- /dev/null
@@ -0,0 +1,140 @@
+//===-- SPIRVBitOps.td - MLIR SPIR-V Bit Ops -*- tablegen -*-===//
+//
+// Copyright 2019 The MLIR Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// =============================================================================
+//
+// This file contains bit ops for the SPIR-V dialect. It corresponds
+// to "3.32.13. Bit Instructions" of the SPIR-V specification.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef SPIRV_BIT_OPS
+#else
+#define SPIRV_BIT_OPS
+
+#ifdef SPIRV_BASE
+#else
+include "mlir/SPIRV/SPIRVBase.td"
+#endif // SPIRV_BASE
+
+class SPV_BitBinaryOp<string mnemonic, list<OpTrait> traits = []> :
+      // All the operands type used in bit instructions are SPV_Integer.
+      SPV_BinaryOp<mnemonic, SPV_Integer, SPV_Integer,
+                   !listconcat(traits,
+                               [NoSideEffect, SameOperandsAndResultType])>;
+
+// -----
+
+def SPV_BitwiseOrOp : SPV_BitBinaryOp<"BitwiseOr", [Commutative]> {
+  let summary = [{
+    Result is 1 if either Operand 1 or Operand 2 is 1. Result is 0 if both
+    Operand 1 and Operand 2 are 0.
+  }];
+
+  let description = [{
+     Results are computed per component, and within each component, per bit.
+
+    Result Type must be a scalar or vector of integer type.  The type of
+    Operand 1 and Operand 2  must be a scalar or vector of integer type.
+    They must have the same number of components as Result Type. They must
+    have the same component width as Result Type.
+
+    ### Custom assembly form
+
+    ``` {.ebnf}
+    integer-scalar-vector-type ::= integer-type |
+                                  `vector<` integer-literal `x` integer-type `>`
+    bitwise-or-op ::= ssa-id `=` `spv.BitwiseOr` ssa-use, ssa-use
+                                  `:` integer-scalar-vector-type
+    ```
+
+    For example:
+
+    ```
+    %2 = spv.BitwiseOr %0, %1 : i32
+    %2 = spv.BitwiseOr %0, %1 : vector<4xi32>
+    ```
+  }];
+}
+
+// -----
+
+def SPV_BitwiseXorOp : SPV_BitBinaryOp<"BitwiseXor", [Commutative]> {
+  let summary = [{
+    Result is 1 if exactly one of Operand 1 or Operand 2 is 1. Result is 0
+    if Operand 1 and Operand 2 have the same value.
+  }];
+
+  let description = [{
+     Results are computed per component, and within each component, per bit.
+
+    Result Type must be a scalar or vector of integer type.  The type of
+    Operand 1 and Operand 2  must be a scalar or vector of integer type.
+    They must have the same number of components as Result Type. They must
+    have the same component width as Result Type.
+
+    ### Custom assembly form
+
+    ``` {.ebnf}
+    integer-scalar-vector-type ::= integer-type |
+                                  `vector<` integer-literal `x` integer-type `>`
+    bitwise-xor-op ::= ssa-id `=` `spv.BitwiseXor` ssa-use, ssa-use
+                                  `:` integer-scalar-vector-type
+    ```
+
+    For example:
+
+    ```
+    %2 = spv.BitwiseXor %0, %1 : i32
+    %2 = spv.BitwiseXor %0, %1 : vector<4xi32>
+    ```
+  }];
+}
+
+// -----
+
+def SPV_BitwiseAndOp : SPV_BitBinaryOp<"BitwiseAnd", [Commutative]> {
+  let summary = [{
+    Result is 1 if both Operand 1 and Operand 2 are 1. Result is 0 if either
+    Operand 1 or Operand 2 are 0.
+  }];
+
+  let description = [{
+     Results are computed per component, and within each component, per bit.
+
+    Result Type must be a scalar or vector of integer type.  The type of
+    Operand 1 and Operand 2  must be a scalar or vector of integer type.
+    They must have the same number of components as Result Type. They must
+    have the same component width as Result Type.
+
+    ### Custom assembly form
+
+    ``` {.ebnf}
+    integer-scalar-vector-type ::= integer-type |
+                                  `vector<` integer-literal `x` integer-type `>`
+    bitwise-and-op ::= ssa-id `=` `spv.BitwiseAnd` ssa-use, ssa-use
+                                  `:` integer-scalar-vector-type
+    ```
+
+    For example:
+
+    ```
+    %2 = spv.BitwiseAnd %0, %1 : i32
+    %2 = spv.BitwiseAnd %0, %1 : vector<4xi32>
+    ```
+  }];
+}
+
+#endif // SPIRV_BIT_OPS
index aa6661a..6bc9148 100644 (file)
@@ -40,6 +40,11 @@ include "mlir/Dialect/SPIRV/SPIRVBase.td"
 include "mlir/Dialect/SPIRV/SPIRVArithmeticOps.td"
 #endif // SPIRV_ARITHMETIC_OPS
 
+#ifdef SPIRV_BIT_OPS
+#else
+include "mlir/Dialect/SPIRV/SPIRVBitOps.td"
+#endif // SPIRV_BIT_OPS
+
 #ifdef SPIRV_CONTROLFLOW_OPS
 #else
 include "mlir/Dialect/SPIRV/SPIRVControlFlowOps.td"
diff --git a/mlir/test/Dialect/SPIRV/bit-ops.mlir b/mlir/test/Dialect/SPIRV/bit-ops.mlir
new file mode 100644 (file)
index 0000000..66998ec
--- /dev/null
@@ -0,0 +1,77 @@
+// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
+
+//===----------------------------------------------------------------------===//
+// spv.BitwiseOr
+//===----------------------------------------------------------------------===//
+
+func @bitwise_or_scalar(%arg: i32) -> i32 {
+  // CHECK: spv.BitwiseOr
+  %0 = spv.BitwiseOr %arg, %arg : i32
+  return %0 : i32
+}
+
+func @bitwise_or_vector(%arg: vector<4xi32>) -> vector<4xi32> {
+  // CHECK: spv.BitwiseOr
+  %0 = spv.BitwiseOr %arg, %arg : vector<4xi32>
+  return %0 : vector<4xi32>
+}
+
+// -----
+
+func @bitwise_or_float(%arg0: f16, %arg1: f16) -> f16 {
+  // expected-error @+1 {{operand #0 must be 8/16/32/64-bit integer or vector of 8/16/32/64-bit integer values of length 2/3/4}}
+  %0 = spv.BitwiseOr %arg0, %arg1 : f16
+  return %0 : f16
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.BitwiseXor
+//===----------------------------------------------------------------------===//
+
+func @bitwise_xor_scalar(%arg: i32) -> i32 {
+  // CHECK: spv.BitwiseXor
+  %0 = spv.BitwiseXor %arg, %arg : i32
+  return %0 : i32
+}
+
+func @bitwise_xor_vector(%arg: vector<4xi32>) -> vector<4xi32> {
+  // CHECK: spv.BitwiseXor
+  %0 = spv.BitwiseXor %arg, %arg : vector<4xi32>
+  return %0 : vector<4xi32>
+}
+
+// -----
+
+func @bitwise_xor_float(%arg0: f16, %arg1: f16) -> f16 {
+  // expected-error @+1 {{operand #0 must be 8/16/32/64-bit integer or vector of 8/16/32/64-bit integer values of length 2/3/4}}
+  %0 = spv.BitwiseXor %arg0, %arg1 : f16
+  return %0 : f16
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.BitwiseAnd
+//===----------------------------------------------------------------------===//
+
+func @bitwise_and_scalar(%arg: i32) -> i32 {
+  // CHECK: spv.BitwiseAnd
+  %0 = spv.BitwiseAnd %arg, %arg : i32
+  return %0 : i32
+}
+
+func @bitwise_and_vector(%arg: vector<4xi32>) -> vector<4xi32> {
+  // CHECK: spv.BitwiseAnd
+  %0 = spv.BitwiseAnd %arg, %arg : vector<4xi32>
+  return %0 : vector<4xi32>
+}
+
+// -----
+
+func @bitwise_and_float(%arg0: f16, %arg1: f16) -> f16 {
+  // expected-error @+1 {{operand #0 must be 8/16/32/64-bit integer or vector of 8/16/32/64-bit integer values of length 2/3/4}}
+  %0 = spv.BitwiseAnd %arg0, %arg1 : f16
+  return %0 : f16
+}