[Mlir-commits] [mlir] 84fe39a - [mlir][emitc] Add a cast op

Marius Brehler llvmlistbot at llvm.org
Thu Apr 28 08:51:37 PDT 2022


Author: Marius Brehler
Date: 2022-04-28T15:50:59Z
New Revision: 84fe39a45b7340d468378f58836c8559fda3959b

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

LOG: [mlir][emitc] Add a cast op

This adds a cast operation that allows to perform an explicit type
conversion. The cast op is emitted as a C-style cast. It can be applied
to integer, float, index and EmitC types.

Reviewed By: jpienaar

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

Added: 
    mlir/test/Target/Cpp/cast.mlir

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

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index e67ac05ebaf20..6ddf10e7935dd 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -16,6 +16,7 @@
 include "mlir/Dialect/EmitC/IR/EmitCAttributes.td"
 include "mlir/Dialect/EmitC/IR/EmitCTypes.td"
 
+include "mlir/Interfaces/CastInterfaces.td"
 include "mlir/Interfaces/SideEffectInterfaces.td"
 
 //===----------------------------------------------------------------------===//
@@ -88,6 +89,33 @@ def EmitC_CallOp : EmitC_Op<"call", []> {
   let hasVerifier = 1;
 }
 
+def EmitC_CastOp : EmitC_Op<"cast", [
+    DeclareOpInterfaceMethods<CastOpInterface>,
+    SameOperandsAndResultShape
+  ]> {
+  let summary = "Cast operation";
+  let description = [{
+    The `cast` operation performs an explicit type conversion and is emitted
+    as a C-style cast expression. It can be applied to integer, float, index
+    and EmitC types.
+
+    Example:
+
+    ```mlir
+    // Cast from `int32_t` to `float`
+    %0 = emitc.cast %arg0: i32 to f32
+
+    // Cast from `void` to `int32_t` pointer
+    %1 = emitc.cast %arg1 :
+        !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
+    ```
+  }];
+
+  let arguments = (ins AnyType:$source);
+  let results = (outs AnyType:$dest);
+  let assemblyFormat = "$source attr-dict `:` type($source) `to` type($dest)";
+}
+
 def EmitC_ConstantOp : EmitC_Op<"constant", [ConstantLike]> {
   let summary = "Constant operation";
   let description = [{

diff  --git a/mlir/lib/Dialect/EmitC/IR/CMakeLists.txt b/mlir/lib/Dialect/EmitC/IR/CMakeLists.txt
index 6283441fdadff..1eaa8ce68ce58 100644
--- a/mlir/lib/Dialect/EmitC/IR/CMakeLists.txt
+++ b/mlir/lib/Dialect/EmitC/IR/CMakeLists.txt
@@ -9,6 +9,7 @@ add_mlir_dialect_library(MLIREmitC
   MLIREmitCAttributesIncGen
 
   LINK_LIBS PUBLIC
+  MLIRCastInterfaces
   MLIRIR
   MLIRSideEffectInterfaces
   )

diff  --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index a1e6db238f607..a310495bffc71 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -62,6 +62,19 @@ LogicalResult ApplyOp::verify() {
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// CastOp
+//===----------------------------------------------------------------------===//
+
+bool CastOp::areCastCompatible(TypeRange inputs, TypeRange outputs) {
+  Type input = inputs.front(), output = outputs.front();
+
+  return ((input.isa<IntegerType, FloatType, IndexType, emitc::OpaqueType,
+                     emitc::PointerType>()) &&
+          (output.isa<IntegerType, FloatType, IndexType, emitc::OpaqueType,
+                      emitc::PointerType>()));
+}
+
 //===----------------------------------------------------------------------===//
 // CallOp
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index dc3336f67b409..4eaa686e56d8f 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -383,6 +383,21 @@ static LogicalResult printOperation(CppEmitter &emitter,
   return success();
 }
 
+static LogicalResult printOperation(CppEmitter &emitter, emitc::CastOp castOp) {
+  raw_ostream &os = emitter.ostream();
+  Operation &op = *castOp.getOperation();
+
+  if (failed(emitter.emitAssignPrefix(op)))
+    return failure();
+  os << "(";
+  if (failed(emitter.emitType(op.getLoc(), op.getResult(0).getType())))
+    return failure();
+  os << ") ";
+  os << emitter.getOrCreateName(castOp.getOperand());
+
+  return success();
+}
+
 static LogicalResult printOperation(CppEmitter &emitter,
                                     emitc::IncludeOp includeOp) {
   raw_ostream &os = emitter.ostream();
@@ -918,7 +933,7 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
           .Case<cf::BranchOp, cf::CondBranchOp>(
               [&](auto op) { return printOperation(*this, op); })
           // EmitC ops.
-          .Case<emitc::ApplyOp, emitc::CallOp, emitc::ConstantOp,
+          .Case<emitc::ApplyOp, emitc::CallOp, emitc::CastOp, emitc::ConstantOp,
                 emitc::IncludeOp, emitc::VariableOp>(
               [&](auto op) { return printOperation(*this, op); })
           // Func ops.

diff  --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index f6e4701d24466..64753b8096fe0 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -93,3 +93,11 @@ func.func @var_attribute_return_type_2() {
     %c0 = "emitc.variable"(){value = "nullptr" : !emitc.ptr<i64>} : () -> !emitc.ptr<i32>
     return
 }
+
+// -----
+
+func.func @cast_tensor(%arg : tensor<f32>) {
+    // expected-error @+1 {{'emitc.cast' op operand type 'tensor<f32>' and result type 'tensor<f32>' are cast incompatible}}
+    %1 = emitc.cast %arg: tensor<f32> to tensor<f32>
+    return
+}

diff  --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
index cce9c281b0265..08b2845ff5d9d 100644
--- a/mlir/test/Dialect/EmitC/ops.mlir
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -12,6 +12,11 @@ func.func @f(%arg0: i32, %f: !emitc.opaque<"int32_t">) {
   return
 }
 
+func.func @cast(%arg0: i32) {
+  %1 = emitc.cast %arg0: i32 to f32
+  return
+}
+
 func.func @c() {
   %1 = "emitc.constant"(){value = 42 : i32} : () -> i32
   return

diff  --git a/mlir/test/Target/Cpp/cast.mlir b/mlir/test/Target/Cpp/cast.mlir
new file mode 100644
index 0000000000000..7254f84e237f4
--- /dev/null
+++ b/mlir/test/Target/Cpp/cast.mlir
@@ -0,0 +1,30 @@
+// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
+// CHECK-LABEL: void cast
+func.func @cast(%arg0 : i32) {
+  // CHECK-NEXT: uint32_t [[V1:[^ ]*]] = (uint32_t) [[V0:[^ ]*]]
+  %1 = emitc.cast %arg0: i32 to ui32
+
+  // CHECK-NEXT: int64_t [[V4:[^ ]*]] = (int64_t) [[V0:[^ ]*]]
+  %2 = emitc.cast %arg0: i32 to i64
+  // CHECK-NEXT: int64_t [[V5:[^ ]*]] = (uint64_t) [[V0:[^ ]*]]
+  %3 = emitc.cast %arg0: i32 to ui64
+
+  // CHECK-NEXT: float [[V4:[^ ]*]] = (float) [[V0:[^ ]*]]
+  %4 = emitc.cast %arg0: i32 to f32
+  // CHECK-NEXT: double [[V5:[^ ]*]] = (double) [[V0:[^ ]*]]
+  %5 = emitc.cast %arg0: i32 to f64
+
+  // CHECK-NEXT: bool [[V6:[^ ]*]] = (bool) [[V0:[^ ]*]]
+  %6 = emitc.cast %arg0: i32 to i1
+
+  // CHECK-NEXT: mytype [[V7:[^ ]*]] = (mytype) [[V0:[^ ]*]]
+  %7 = emitc.cast %arg0: i32 to !emitc.opaque<"mytype">
+  return
+}
+
+// CHECK-LABEL: void cast_ptr
+func.func @cast_ptr(%arg0 : !emitc.ptr<!emitc.opaque<"void">>) {
+  // CHECK-NEXT: int32_t* [[V1:[^ ]*]] = (int32_t*) [[V0:[^ ]*]]
+  %1 = emitc.cast %arg0 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
+  return
+}


        


More information about the Mlir-commits mailing list