[Mlir-commits] [mlir] a2426eb - [mlir][emitc] Add div, mul and rem operators

Marius Brehler llvmlistbot at llvm.org
Tue Jul 11 23:44:37 PDT 2023


Author: Marius Brehler
Date: 2023-07-12T08:45:10+02:00
New Revision: a2426eb603afaf6c04ddd14921b474d2caffa12b

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

LOG: [mlir][emitc] Add div, mul and rem operators

This adds operations for binary multiplicative arithmetic operators to
EmitC. The input and output arguments for the remainder operator are
restricted to index (emitted as size_t), integers and the EmitC opaque
types (as the operator can be overloaded for a custom type). The
multiplication and division operator further support floating point
numbers.

Reviewed By: jpienaar

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

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
    mlir/lib/Target/Cpp/TranslateToCpp.cpp
    mlir/test/Dialect/EmitC/invalid_ops.mlir
    mlir/test/Dialect/EmitC/ops.mlir
    mlir/test/Target/Cpp/arithmetic_operators.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 93cffcd891cb8f..ddf6c41468be71 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -33,10 +33,12 @@ class EmitC_BinaryArithOp<string mnemonic, list<Trait> traits = []> :
   let arguments = (ins AnyType:$lhs, AnyType:$rhs);
   let results = (outs AnyType);
   let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
-
-  let hasVerifier = 1;
 }
 
+// Types only used in binary arithmetic operations.
+def IntegerIndexOrOpaqueType : AnyTypeOf<[AnyInteger, Index, EmitC_OpaqueType]>;
+def FloatIntegerIndexOrOpaqueType : AnyTypeOf<[AnyFloat, IntegerIndexOrOpaqueType]>;
+
 def EmitC_AddOp : EmitC_BinaryArithOp<"add", []> {
   let summary = "Addition operation";
   let description = [{
@@ -56,6 +58,8 @@ def EmitC_AddOp : EmitC_BinaryArithOp<"add", []> {
     float* v6 = v3 + v4;
     ```
   }];
+
+  let hasVerifier = 1;
 }
 
 def EmitC_ApplyOp : EmitC_Op<"apply", []> {
@@ -176,6 +180,30 @@ def EmitC_ConstantOp : EmitC_Op<"constant", [ConstantLike]> {
   let hasVerifier = 1;
 }
 
+def EmitC_DivOp : EmitC_BinaryArithOp<"div", []> {
+  let summary = "Division operation";
+  let description = [{
+    With the `div` operation the arithmetic operator / (division) can
+    be applied.
+
+    Example:
+
+    ```mlir
+    // Custom form of the division operation.
+    %0 = emitc.div %arg0, %arg1 : (i32, i32) -> i32
+    %1 = emitc.div %arg2, %arg3 : (f32, f32) -> f32
+    ```
+    ```c++
+    // Code emitted for the operations above.
+    int32_t v5 = v1 / v2;
+    float v6 = v3 / v4;
+    ```
+  }];
+
+  let arguments = (ins FloatIntegerIndexOrOpaqueType, FloatIntegerIndexOrOpaqueType);
+  let results = (outs FloatIntegerIndexOrOpaqueType);
+}
+
 def EmitC_IncludeOp
     : EmitC_Op<"include", [HasParent<"ModuleOp">]> {
   let summary = "Include operation";
@@ -206,6 +234,52 @@ def EmitC_IncludeOp
   let hasCustomAssemblyFormat = 1;
 }
 
+def EmitC_MulOp : EmitC_BinaryArithOp<"mul", []> {
+  let summary = "Multiplication operation";
+  let description = [{
+    With the `mul` operation the arithmetic operator * (multiplication) can
+    be applied.
+
+    Example:
+
+    ```mlir
+    // Custom form of the multiplication operation.
+    %0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
+    %1 = emitc.mul %arg2, %arg3 : (f32, f32) -> f32
+    ```
+    ```c++
+    // Code emitted for the operations above.
+    int32_t v5 = v1 * v2;
+    float v6 = v3 * v4;
+    ```
+  }];
+
+  let arguments = (ins FloatIntegerIndexOrOpaqueType, FloatIntegerIndexOrOpaqueType);
+  let results = (outs FloatIntegerIndexOrOpaqueType);
+}
+
+def EmitC_RemOp : EmitC_BinaryArithOp<"rem", []> {
+  let summary = "Remainder operation";
+  let description = [{
+    With the `rem` operation the arithmetic operator % (remainder) can
+    be applied.
+
+    Example:
+
+    ```mlir
+    // Custom form of the remainder operation.
+    %0 = emitc.rem %arg0, %arg1 : (i32, i32) -> i32
+    ```
+    ```c++
+    // Code emitted for the operation above.
+    int32_t v5 = v1 % v2;
+    ```
+  }];
+
+  let arguments = (ins IntegerIndexOrOpaqueType, IntegerIndexOrOpaqueType);
+  let results = (outs IntegerIndexOrOpaqueType);
+}
+
 def EmitC_SubOp : EmitC_BinaryArithOp<"sub", []> {
   let summary = "Subtraction operation";
   let description = [{
@@ -228,6 +302,8 @@ def EmitC_SubOp : EmitC_BinaryArithOp<"sub", []> {
     ptr
diff _t v9 = v5 - v6;
     ```
   }];
+
+  let hasVerifier = 1;
 }
 
 def EmitC_VariableOp : EmitC_Op<"variable", []> {

diff  --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index a1f6886a8ae4d1..2ac6915a1c182e 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -266,6 +266,24 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::AddOp addOp) {
   return printBinaryArithOperation(emitter, operation, "+");
 }
 
+static LogicalResult printOperation(CppEmitter &emitter, emitc::DivOp divOp) {
+  Operation *operation = divOp.getOperation();
+
+  return printBinaryArithOperation(emitter, operation, "/");
+}
+
+static LogicalResult printOperation(CppEmitter &emitter, emitc::MulOp mulOp) {
+  Operation *operation = mulOp.getOperation();
+
+  return printBinaryArithOperation(emitter, operation, "*");
+}
+
+static LogicalResult printOperation(CppEmitter &emitter, emitc::RemOp remOp) {
+  Operation *operation = remOp.getOperation();
+
+  return printBinaryArithOperation(emitter, operation, "%");
+}
+
 static LogicalResult printOperation(CppEmitter &emitter, emitc::SubOp subOp) {
   Operation *operation = subOp.getOperation();
 
@@ -957,8 +975,8 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
               [&](auto op) { return printOperation(*this, op); })
           // EmitC ops.
           .Case<emitc::AddOp, emitc::ApplyOp, emitc::CallOp, emitc::CastOp,
-                emitc::ConstantOp, emitc::IncludeOp, emitc::SubOp,
-                emitc::VariableOp>(
+                emitc::ConstantOp, emitc::DivOp, emitc::IncludeOp, emitc::MulOp,
+                emitc::RemOp, emitc::SubOp, emitc::VariableOp>(
               [&](auto op) { return printOperation(*this, op); })
           // Func ops.
           .Case<func::CallOp, func::ConstantOp, func::FuncOp, func::ReturnOp>(

diff  --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index 2c45d49a7e3714..3978f906525b88 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -145,6 +145,38 @@ func.func @add_float_pointer(%arg0: f32, %arg1: !emitc.ptr<f32>) {
 
 // -----
 
+func.func @div_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) {
+    // expected-error @+1 {{'emitc.div' op operand #0 must be floating-point or integer or index or EmitC opaque type, but got 'tensor<i32>'}}
+    %1 = "emitc.div" (%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
+    return
+}
+
+// -----
+
+func.func @mul_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) {
+    // expected-error @+1 {{'emitc.mul' op operand #0 must be floating-point or integer or index or EmitC opaque type, but got 'tensor<i32>'}}
+    %1 = "emitc.mul" (%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
+    return
+}
+
+// -----
+
+func.func @rem_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) {
+    // expected-error @+1 {{'emitc.rem' op operand #0 must be integer or index or EmitC opaque type, but got 'tensor<i32>'}}
+    %1 = "emitc.rem" (%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
+    return
+}
+
+// -----
+
+func.func @rem_float(%arg0: f32, %arg1: f32) {
+    // expected-error @+1 {{'emitc.rem' op operand #0 must be integer or index or EmitC opaque type, but got 'f32'}}
+    %1 = "emitc.rem" (%arg0, %arg1) : (f32, f32) -> f32
+    return
+}
+
+// -----
+
 func.func @sub_int_pointer(%arg0: i32, %arg1: !emitc.ptr<f32>) {
     // expected-error @+1 {{'emitc.sub' op rhs can only be a pointer if lhs is a pointer}}
     %1 = "emitc.sub" (%arg0, %arg1) : (i32, !emitc.ptr<f32>) -> !emitc.ptr<f32>

diff  --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
index a1d226b3794304..4f08601d6ac403 100644
--- a/mlir/test/Dialect/EmitC/ops.mlir
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -42,6 +42,31 @@ func.func @add_pointer(%arg0: !emitc.ptr<f32>, %arg1: i32, %arg2: !emitc.opaque<
   return
 }
 
+func.func @div_int(%arg0: i32, %arg1: i32) {
+  %1 = "emitc.div" (%arg0, %arg1) : (i32, i32) -> i32
+  return
+}
+
+func.func @div_float(%arg0: f32, %arg1: f32) {
+  %1 = "emitc.div" (%arg0, %arg1) : (f32, f32) -> f32
+  return
+}
+
+func.func @mul_int(%arg0: i32, %arg1: i32) {
+  %1 = "emitc.mul" (%arg0, %arg1) : (i32, i32) -> i32
+  return
+}
+
+func.func @mul_float(%arg0: f32, %arg1: f32) {
+  %1 = "emitc.mul" (%arg0, %arg1) : (f32, f32) -> f32
+  return
+}
+
+func.func @rem(%arg0: i32, %arg1: i32) {
+  %1 = "emitc.rem" (%arg0, %arg1) : (i32, i32) -> i32
+  return
+}
+
 func.func @sub_int(%arg0: i32, %arg1: i32) {
   %1 = "emitc.sub" (%arg0, %arg1) : (i32, i32) -> i32
   return

diff  --git a/mlir/test/Target/Cpp/arithmetic_operators.mlir b/mlir/test/Target/Cpp/arithmetic_operators.mlir
index 0ce1af45ac9a75..540c473f26dde3 100644
--- a/mlir/test/Target/Cpp/arithmetic_operators.mlir
+++ b/mlir/test/Target/Cpp/arithmetic_operators.mlir
@@ -14,6 +14,27 @@ func.func @add_pointer(%arg0: !emitc.ptr<f32>, %arg1: i32) {
 // CHECK-LABEL: void add_pointer
 // CHECK-NEXT:  float* [[V2:[^ ]*]] = [[V0:[^ ]*]] + [[V1:[^ ]*]]
 
+func.func @div_int(%arg0: i32, %arg1: i32) {
+  %1 = "emitc.div" (%arg0, %arg1) : (i32, i32) -> i32
+  return
+}
+// CHECK-LABEL: void div_int
+// CHECK-NEXT:  int32_t [[V2:[^ ]*]] = [[V0:[^ ]*]] / [[V1:[^ ]*]]
+
+func.func @mul_int(%arg0: i32, %arg1: i32) {
+  %1 = "emitc.mul" (%arg0, %arg1) : (i32, i32) -> i32
+  return
+}
+// CHECK-LABEL: void mul_int
+// CHECK-NEXT:  int32_t [[V2:[^ ]*]] = [[V0:[^ ]*]] * [[V1:[^ ]*]]
+
+func.func @rem(%arg0: i32, %arg1: i32) {
+  %1 = "emitc.rem" (%arg0, %arg1) : (i32, i32) -> i32
+  return
+}
+// CHECK-LABEL: void rem
+// CHECK-NEXT:  int32_t [[V2:[^ ]*]] = [[V0:[^ ]*]] % [[V1:[^ ]*]]
+
 func.func @sub_int(%arg0: i32, %arg1: i32) {
   %1 = "emitc.sub" (%arg0, %arg1) : (i32, i32) -> i32
   return


        


More information about the Mlir-commits mailing list