[spirv] Add binary arithmetic operations tensorflow/mlir#2.
authorDenis Khalikov <dennis.khalikov@gmail.com>
Wed, 31 Jul 2019 18:10:17 +0000 (11:10 -0700)
committerA. Unique TensorFlower <gardener@tensorflow.org>
Wed, 31 Jul 2019 18:10:50 +0000 (11:10 -0700)
Add binary operations such as: OpUdiv, OpSDiv, OpUMod, OpSRem, OpSMod.

Closes tensorflow/mlir#56

COPYBARA_INTEGRATE_REVIEW=https://github.com/tensorflow/mlir/pull/56 from denis0x0D:sandbox/bin_ops_int 4959325a693b4658b978a8b97f79b8237eb39764
PiperOrigin-RevId: 260961681

mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
mlir/include/mlir/Dialect/SPIRV/SPIRVOps.td
mlir/test/Dialect/SPIRV/Serialization/bin_ops.mlir
mlir/test/Dialect/SPIRV/ops.mlir

index a820c11..838d42e 100644 (file)
@@ -105,7 +105,12 @@ def SPV_OC_OpISub              : I32EnumAttrCase<"OpISub", 130>;
 def SPV_OC_OpFSub              : I32EnumAttrCase<"OpFSub", 131>;
 def SPV_OC_OpIMul              : I32EnumAttrCase<"OpIMul", 132>;
 def SPV_OC_OpFMul              : I32EnumAttrCase<"OpFMul", 133>;
+def SPV_OC_OpUDiv              : I32EnumAttrCase<"OpUDiv", 134>;
+def SPV_OC_OpSDiv              : I32EnumAttrCase<"OpSDiv", 135>;
 def SPV_OC_OpFDiv              : I32EnumAttrCase<"OpFDiv", 136>;
+def SPV_OC_OpUMod              : I32EnumAttrCase<"OpUMod", 137>;
+def SPV_OC_OpSRem              : I32EnumAttrCase<"OpSRem", 138>;
+def SPV_OC_OpSMod              : I32EnumAttrCase<"OpSMod", 139>;
 def SPV_OC_OpFRem              : I32EnumAttrCase<"OpFRem", 140>;
 def SPV_OC_OpFMod              : I32EnumAttrCase<"OpFMod", 141>;
 def SPV_OC_OpReturn            : I32EnumAttrCase<"OpReturn", 253>;
@@ -121,7 +126,8 @@ def SPV_OpcodeAttr :
       SPV_OC_OpFunctionEnd, SPV_OC_OpVariable, SPV_OC_OpLoad, SPV_OC_OpStore,
       SPV_OC_OpAccessChain, SPV_OC_OpDecorate, SPV_OC_OpCompositeExtract,
       SPV_OC_OpIAdd, SPV_OC_OpFAdd, SPV_OC_OpISub, SPV_OC_OpFSub, SPV_OC_OpIMul,
-      SPV_OC_OpFMul, SPV_OC_OpFDiv, SPV_OC_OpFRem, SPV_OC_OpFMod, SPV_OC_OpReturn
+      SPV_OC_OpFMul, SPV_OC_OpUDiv, SPV_OC_OpSDiv, SPV_OC_OpFDiv, SPV_OC_OpUMod,
+      SPV_OC_OpSRem, SPV_OC_OpSMod, SPV_OC_OpFRem, SPV_OC_OpFMod, SPV_OC_OpReturn
       ]> {
     let returnType = "::mlir::spirv::Opcode";
     let convertFromStorage = "static_cast<::mlir::spirv::Opcode>($_self.getInt())";
index 8f97f78..b0f2809 100644 (file)
@@ -623,6 +623,113 @@ def SPV_ReturnOp : SPV_Op<"Return", [Terminator]> {
 
 // -----
 
+def SPV_SDivOp : SPV_ArithmeticOp<"SDiv", SPV_Integer> {
+  let summary = "Signed-integer division of Operand 1 divided by Operand 2.";
+
+  let description = [{
+    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.
+
+     Results are computed per component.  The resulting value is undefined
+    if Operand 2 is 0.
+
+    ### Custom assembly form
+    ``` {.ebnf}
+    integer-scalar-vector-type ::= integer-type |
+                                 `vector<` integer-literal `x` integer-type `>`
+    sdiv-op ::= ssa-id `=` `spv.SDiv` ssa-use, ssa-use
+                           `:` integer-scalar-vector-type
+    ```
+
+    For example:
+
+    ```
+    %4 = spv.SDiv %0, %1 : i32
+    %5 = spv.SDiv %2, %3 : vector<4xi32>
+
+    ```
+  }];
+}
+
+// -----
+
+def SPV_SModOp : SPV_ArithmeticOp<"SMod", SPV_Integer> {
+  let summary = [{
+    Signed remainder operation for the remainder whose sign matches the sign
+    of Operand 2.
+  }];
+
+  let description = [{
+    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.
+
+     Results are computed per component.  The resulting value is undefined
+    if Operand 2 is 0.  Otherwise, the result is the remainder r of Operand
+    1 divided by Operand 2 where if r ≠ 0, the sign of r is the same as the
+    sign of Operand 2.
+
+    ### Custom assembly form
+    ``` {.ebnf}
+    integer-scalar-vector-type ::= integer-type |
+                                 `vector<` integer-literal `x` integer-type `>`
+    smod-op ::= ssa-id `=` `spv.SMod` ssa-use, ssa-use
+                           `:` integer-scalar-vector-type
+    ```
+    For example:
+
+    ```
+    %4 = spv.SMod %0, %1 : i32
+    %5 = spv.SMod %2, %3 : vector<4xi32>
+
+    ```
+  }];
+}
+
+// -----
+
+def SPV_SRemOp : SPV_ArithmeticOp<"SRem", SPV_Integer> {
+  let summary = [{
+    Signed remainder operation for the remainder whose sign matches the sign
+    of Operand 1.
+  }];
+
+  let description = [{
+    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.
+
+     Results are computed per component.  The resulting value is undefined
+    if Operand 2 is 0.  Otherwise, the result is the remainder r of Operand
+    1 divided by Operand 2 where if r ≠ 0, the sign of r is the same as the
+    sign of Operand 1.
+
+    ### Custom assembly form
+    ``` {.ebnf}
+    integer-scalar-vector-type ::= integer-type |
+                                 `vector<` integer-literal `x` integer-type `>`
+    srem-op ::= ssa-id `=` `spv.SRem` ssa-use, ssa-use
+                           `:` integer-scalar-vector-type
+    ```
+    For example:
+
+    ```
+    %4 = spv.SRem %0, %1 : i32
+    %5 = spv.SRem %2, %3 : vector<4xi32>
+
+    ```
+  }];
+}
+
+// -----
+
 def SPV_StoreOp : SPV_Op<"Store", []> {
   let summary = "Store through a pointer.";
 
@@ -665,6 +772,70 @@ def SPV_StoreOp : SPV_Op<"Store", []> {
 
 // -----
 
+def SPV_UDivOp : SPV_ArithmeticOp<"UDiv", SPV_Integer> {
+  let summary = "Unsigned-integer division of Operand 1 divided by Operand 2.";
+
+  let description = [{
+    Result Type must be a scalar or vector of integer type, whose Signedness
+    operand is 0.
+
+     The types of Operand 1 and Operand 2 both must be the same as Result
+    Type.
+
+     Results are computed per component.  The resulting value is undefined
+    if Operand 2 is 0.
+
+    ### Custom assembly form
+    ``` {.ebnf}
+    integer-scalar-vector-type ::= integer-type |
+                                 `vector<` integer-literal `x` integer-type `>`
+    udiv-op ::= ssa-id `=` `spv.UDiv` ssa-use, ssa-use
+                           `:` integer-scalar-vector-type
+    ```
+    For example:
+
+    ```
+    %4 = spv.UDiv %0, %1 : i32
+    %5 = spv.UDiv %2, %3 : vector<4xi32>
+
+    ```
+  }];
+}
+
+// -----
+
+def SPV_UModOp : SPV_ArithmeticOp<"UMod", SPV_Integer> {
+  let summary = "Unsigned modulo operation of Operand 1 modulo Operand 2.";
+
+  let description = [{
+    Result Type must be a scalar or vector of integer type, whose Signedness
+    operand is 0.
+
+     The types of Operand 1 and Operand 2 both must be the same as Result
+    Type.
+
+     Results are computed per component.  The resulting value is undefined
+    if Operand 2 is 0.
+
+    ### Custom assembly form
+    ``` {.ebnf}
+    integer-scalar-vector-type ::= integer-type |
+                                 `vector<` integer-literal `x` integer-type `>`
+    umod-op ::= ssa-id `=` `spv.UMod` ssa-use, ssa-use
+                           `:` integer-scalar-vector-type
+    ```
+    For example:
+
+    ```
+    %4 = spv.UMod %0, %1 : i32
+    %5 = spv.UMod %2, %3 : vector<4xi32>
+
+    ```
+  }];
+}
+
+// -----
+
 def SPV_VariableOp : SPV_Op<"Variable", []> {
   let summary = [{
     Allocate an object in memory, resulting in a pointer to it, which can be
index e7d5ac6..4996fb8 100644 (file)
@@ -47,6 +47,31 @@ func @spirv_bin_ops() -> () {
       %0 = spv.IMul %arg0, %arg1 : vector<4xi32>
       spv.Return
     }
+    func @udiv(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) {
+      // CHECK: {{%.*}} = spv.UDiv {{%.*}}, {{%.*}} : vector<4xi32>
+      %0 = spv.UDiv %arg0, %arg1 : vector<4xi32>
+      spv.Return
+    }
+    func @umod(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) {
+      // CHECK: {{%.*}} = spv.UMod {{%.*}}, {{%.*}} : vector<4xi32>
+      %0 = spv.UMod %arg0, %arg1 : vector<4xi32>
+      spv.Return
+    }
+    func @sdiv(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) {
+      // CHECK: {{%.*}} = spv.SDiv {{%.*}}, {{%.*}} : vector<4xi32>
+      %0 = spv.SDiv %arg0, %arg1 : vector<4xi32>
+      spv.Return
+    }
+    func @smod(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) {
+      // CHECK: {{%.*}} = spv.SMod {{%.*}}, {{%.*}} : vector<4xi32>
+      %0 = spv.SMod %arg0, %arg1 : vector<4xi32>
+      spv.Return
+    }
+    func @srem(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) {
+      // CHECK: {{%.*}} = spv.SRem {{%.*}}, {{%.*}} : vector<4xi32>
+      %0 = spv.SRem %arg0, %arg1 : vector<4xi32>
+      spv.Return
+    }
   }
   return
 }
index ebc5b6c..8ced513 100644 (file)
@@ -660,6 +660,66 @@ spv.module "Logical" "VulkanKHR" {
 // -----
 
 //===----------------------------------------------------------------------===//
+// spv.SDiv
+//===----------------------------------------------------------------------===//
+
+func @sdiv_scalar(%arg: i32) -> i32 {
+  // CHECK: spv.SDiv
+  %0 = spv.SDiv %arg, %arg : i32
+  return %0 : i32
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.SMod
+//===----------------------------------------------------------------------===//
+
+func @smod_scalar(%arg: i32) -> i32 {
+  // CHECK: spv.SMod
+  %0 = spv.SMod %arg, %arg : i32
+  return %0 : i32
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.SRem
+//===----------------------------------------------------------------------===//
+
+func @srem_scalar(%arg: i32) -> i32 {
+  // CHECK: spv.SRem
+  %0 = spv.SRem %arg, %arg : i32
+  return %0 : i32
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.UDiv
+//===----------------------------------------------------------------------===//
+
+func @udiv_scalar(%arg: i32) -> i32 {
+  // CHECK: spv.UDiv
+  %0 = spv.UDiv %arg, %arg : i32
+  return %0 : i32
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.UMod
+//===----------------------------------------------------------------------===//
+
+func @umod_scalar(%arg: i32) -> i32 {
+  // CHECK: spv.UMod
+  %0 = spv.UMod %arg, %arg : i32
+  return %0 : i32
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
 // spv.StoreOp
 //===----------------------------------------------------------------------===//