[Mlir-commits] [mlir] c78219f - [mlir] Add a new builtin `unrealized_conversion_cast` operation

River Riddle llvmlistbot at llvm.org
Wed Jan 20 16:28:31 PST 2021


Author: River Riddle
Date: 2021-01-20T16:28:18-08:00
New Revision: c78219f644c7a6e352cd416f8ebb4374b745967e

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

LOG: [mlir] Add a new builtin `unrealized_conversion_cast` operation

An `unrealized_conversion_cast` operation represents an unrealized conversion
from one set of types to another, that is used to enable the inter-mixing of
different type systems. This operation should not be attributed any special
representational or execution semantics, and is generally only intended to be
used to satisfy the temporary intermixing of type systems during the conversion
of one type system to another.

This operation was discussed in the following RFC(and ODM):

https://llvm.discourse.group/t/open-meeting-1-14-dialect-conversion-and-type-conversion-the-question-of-cast-operations/

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

Added: 
    mlir/test/Dialect/Builtin/canonicalize.mlir
    mlir/test/Dialect/Builtin/invalid.mlir
    mlir/test/Dialect/Builtin/ops.mlir

Modified: 
    mlir/include/mlir/IR/BuiltinOps.h
    mlir/include/mlir/IR/BuiltinOps.td
    mlir/lib/IR/BuiltinDialect.cpp
    mlir/lib/IR/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/IR/BuiltinOps.h b/mlir/include/mlir/IR/BuiltinOps.h
index c695a005283b..c0163b148f3c 100644
--- a/mlir/include/mlir/IR/BuiltinOps.h
+++ b/mlir/include/mlir/IR/BuiltinOps.h
@@ -17,6 +17,8 @@
 #include "mlir/IR/OwningOpRef.h"
 #include "mlir/IR/SymbolTable.h"
 #include "mlir/Interfaces/CallInterfaces.h"
+#include "mlir/Interfaces/CastInterfaces.h"
+#include "mlir/Interfaces/SideEffectInterfaces.h"
 #include "llvm/Support/PointerLikeTypeTraits.h"
 
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/IR/BuiltinOps.td b/mlir/include/mlir/IR/BuiltinOps.td
index 86de251094cd..2c4d47d61cbe 100644
--- a/mlir/include/mlir/IR/BuiltinOps.td
+++ b/mlir/include/mlir/IR/BuiltinOps.td
@@ -17,6 +17,8 @@
 include "mlir/IR/BuiltinDialect.td"
 include "mlir/IR/SymbolInterfaces.td"
 include "mlir/Interfaces/CallInterfaces.td"
+include "mlir/Interfaces/CastInterfaces.td"
+include "mlir/Interfaces/SideEffectInterfaces.td"
 
 // Base class for Builtin dialect ops.
 class Builtin_Op<string mnemonic, list<OpTrait> traits = []> :
@@ -220,4 +222,53 @@ def ModuleTerminatorOp : Builtin_Op<"module_terminator", [
   let assemblyFormat = "attr-dict";
 }
 
+//===----------------------------------------------------------------------===//
+// UnrealizedConversionCastOp
+//===----------------------------------------------------------------------===//
+
+def UnrealizedConversionCastOp : Builtin_Op<"unrealized_conversion_cast", [
+    DeclareOpInterfaceMethods<CastOpInterface>, NoSideEffect
+  ]> {
+  let summary = "An unrealized conversion from one set of types to another";
+  let description = [{
+    An `unrealized_conversion_cast` operation represents an unrealized
+    conversion from one set of types to another, that is used to enable the
+    inter-mixing of 
diff erent type systems. This operation should not be
+    attributed any special representational or execution semantics, and is
+    generally only intended to be used to satisfy the temporary intermixing of
+    type systems during the conversion of one type system to another.
+
+    This operation may produce results of arity 1-N, and accept as input
+    operands of arity 0-N.
+
+    Example:
+
+    ```mlir
+    // An unrealized 0-1 conversion. These types of conversions are useful in
+    // cases where a type is removed from the type system, but not all uses have
+    // been converted. For example, imagine we have a tuple type that is
+    // expanded to its element types. If only some uses of an empty tuple type
+    // instance are converted we still need an instance of the tuple type, but
+    // have no inputs to the unrealized conversion.
+    %result = unrealized_conversion_cast to !bar.tuple_type<>
+
+    // An unrealized 1-1 conversion.
+    %result1 = unrealized_conversion_cast %operand : !foo.type to !bar.lowered_type
+
+    // An unrealized 1-N conversion.
+    %results2:2 = unrealized_conversion_cast %tuple_operand : !foo.tuple_type<!foo.type, !foo.type> to !foo.type, !foo.type
+
+    // An unrealized N-1 conversion.
+    %result3 = unrealized_conversion_cast %operand, %operand : !foo.type, !foo.type to !bar.tuple_type<!foo.type, !foo.type>
+    ```
+  }];
+
+  let arguments = (ins Variadic<AnyType>:$inputs);
+  let results = (outs Variadic<AnyType>:$outputs);
+  let assemblyFormat = [{
+    ($inputs^ `:` type($inputs))? `to` type($outputs) attr-dict
+  }];
+  let hasFolder = 1;
+}
+
 #endif // BUILTIN_OPS

diff  --git a/mlir/lib/IR/BuiltinDialect.cpp b/mlir/lib/IR/BuiltinDialect.cpp
index 2cd90f3d0fde..138321e734e2 100644
--- a/mlir/lib/IR/BuiltinDialect.cpp
+++ b/mlir/lib/IR/BuiltinDialect.cpp
@@ -18,6 +18,7 @@
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/FunctionImplementation.h"
 #include "mlir/IR/OpImplementation.h"
+#include "mlir/IR/PatternMatch.h"
 #include "llvm/ADT/MapVector.h"
 
 using namespace mlir;
@@ -236,6 +237,38 @@ static LogicalResult verify(ModuleOp op) {
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// UnrealizedConversionCastOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult
+UnrealizedConversionCastOp::fold(ArrayRef<Attribute> attrOperands,
+                                 SmallVectorImpl<OpFoldResult> &foldResults) {
+  OperandRange operands = inputs();
+  if (operands.empty())
+    return failure();
+
+  // Check that the input is a cast with results that all feed into this
+  // operation, and operand types that directly match the result types of this
+  // operation.
+  ResultRange results = outputs();
+  Value firstInput = operands.front();
+  auto inputOp = firstInput.getDefiningOp<UnrealizedConversionCastOp>();
+  if (!inputOp || inputOp.getResults() != operands ||
+      inputOp.getOperandTypes() != results.getTypes())
+    return failure();
+
+  // If everything matches up, we can fold the passthrough.
+  foldResults.append(inputOp->operand_begin(), inputOp->operand_end());
+  return success();
+}
+
+bool UnrealizedConversionCastOp::areCastCompatible(TypeRange inputs,
+                                                   TypeRange outputs) {
+  // `UnrealizedConversionCastOp` is agnostic of the input/output types.
+  return true;
+}
+
 //===----------------------------------------------------------------------===//
 // TableGen'd op method definitions
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/lib/IR/CMakeLists.txt b/mlir/lib/IR/CMakeLists.txt
index e4b3b9141323..f9ab7033eb48 100644
--- a/mlir/lib/IR/CMakeLists.txt
+++ b/mlir/lib/IR/CMakeLists.txt
@@ -37,8 +37,10 @@ add_mlir_library(MLIRIR
   MLIRBuiltinOpsIncGen
   MLIRBuiltinTypesIncGen
   MLIRCallInterfacesIncGen
+  MLIRCastInterfacesIncGen
   MLIROpAsmInterfaceIncGen
   MLIRRegionKindInterfaceIncGen
+  MLIRSideEffectInterfacesIncGen
   MLIRSymbolInterfacesIncGen
 
   LINK_LIBS PUBLIC

diff  --git a/mlir/test/Dialect/Builtin/canonicalize.mlir b/mlir/test/Dialect/Builtin/canonicalize.mlir
new file mode 100644
index 000000000000..316684428f2d
--- /dev/null
+++ b/mlir/test/Dialect/Builtin/canonicalize.mlir
@@ -0,0 +1,25 @@
+// RUN: mlir-opt %s -canonicalize | FileCheck %s
+
+//===----------------------------------------------------------------------===//
+// UnrealizedConversionCastOp
+//===----------------------------------------------------------------------===//
+
+// Test folding conversion casts feeding into other casts.
+// CHECK-LABEL: func @multiple_conversion_casts
+// CHECK-SAME: %[[ARG0:.*]]: i32, %[[ARG1:.*]]:
+func @multiple_conversion_casts(%arg0: i32, %arg1: i32) -> (i32, i32) {
+  // CHECK-NOT: unrealized_conversion_cast
+  // CHECK: return %[[ARG0]], %[[ARG1]]
+  %inputs:2 = unrealized_conversion_cast %arg0, %arg1 : i32, i32 to i64, i64
+  %outputs:2 = unrealized_conversion_cast %inputs#0, %inputs#1 : i64, i64 to i32, i32
+  return %outputs#0, %outputs#1 : i32, i32
+}
+
+// CHECK-LABEL: func @multiple_conversion_casts
+func @multiple_conversion_casts_failure(%arg0: i32, %arg1: i32, %arg2: i64) -> (i32, i32) {
+  // CHECK: unrealized_conversion_cast
+  // CHECK: unrealized_conversion_cast
+  %inputs:2 = unrealized_conversion_cast %arg0, %arg1 : i32, i32 to i64, i64
+  %outputs:2 = unrealized_conversion_cast %arg2, %inputs#1 : i64, i64 to i32, i32
+  return %outputs#0, %outputs#1 : i32, i32
+}

diff  --git a/mlir/test/Dialect/Builtin/invalid.mlir b/mlir/test/Dialect/Builtin/invalid.mlir
new file mode 100644
index 000000000000..e7b08407d8a8
--- /dev/null
+++ b/mlir/test/Dialect/Builtin/invalid.mlir
@@ -0,0 +1,11 @@
+// RUN: mlir-opt %s -split-input-file -verify-diagnostics
+
+//===----------------------------------------------------------------------===//
+// UnrealizedConversionCastOp
+//===----------------------------------------------------------------------===//
+
+// expected-error at +1 {{expected at least one result for cast operation}}
+"unrealized_conversion_cast"() : () -> ()
+
+// -----
+

diff  --git a/mlir/test/Dialect/Builtin/ops.mlir b/mlir/test/Dialect/Builtin/ops.mlir
new file mode 100644
index 000000000000..e1ef6f196bd5
--- /dev/null
+++ b/mlir/test/Dialect/Builtin/ops.mlir
@@ -0,0 +1,20 @@
+// RUN: mlir-opt %s -allow-unregistered-dialect | mlir-opt -allow-unregistered-dialect
+
+//===----------------------------------------------------------------------===//
+// UnrealizedConversionCastOp
+//===----------------------------------------------------------------------===//
+
+%operand = "foo.op"() : () -> !foo.type
+%tuple_operand = "foo.op"() : () -> !foo.tuple_type<!foo.type, !foo.type>
+
+// An unrealized 0-1 conversion.
+%result = unrealized_conversion_cast to !bar.tuple_type<>
+
+// An unrealized 1-1 conversion.
+%result1 = unrealized_conversion_cast %operand : !foo.type to !bar.lowered_type
+
+// An unrealized 1-N conversion.
+%results2:2 = unrealized_conversion_cast %tuple_operand : !foo.tuple_type<!foo.type, !foo.type> to !foo.type, !foo.type
+
+// An unrealized N-1 conversion.
+%result3 = unrealized_conversion_cast %operand, %operand : !foo.type, !foo.type to !bar.tuple_type<!foo.type, !foo.type>


        


More information about the Mlir-commits mailing list