-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[MLIR][Test] Extend coverage of unrealized_conversion_cast operation #142152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-mlir Author: Peyman B (peymanbr) ChangesAdds a suite of IR tests for the unrealized_conversion_cast operation, covering a wide range of type conversion scenarios and edge cases:
These tests help guard against regressions and provide a robust reference for dialect authors using unrealized_conversion_cast in type conversion scenarios across dialect boundaries. Patch is 26.26 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/142152.diff 1 Files Affected:
diff --git a/mlir/test/IR/unrealized-conversion-cast.mlir b/mlir/test/IR/unrealized-conversion-cast.mlir
new file mode 100644
index 0000000000000..8df24652bb9a4
--- /dev/null
+++ b/mlir/test/IR/unrealized-conversion-cast.mlir
@@ -0,0 +1,677 @@
+// RUN: mlir-opt %s -verify-diagnostics -split-input-file \
+// RUN: -allow-unregistered-dialect
+// RUN: mlir-opt %s -reconcile-unrealized-casts -split-input-file \
+// RUN: -allow-unregistered-dialect | FileCheck %s --check-prefix=RECONCILE
+// RUN: mlir-opt %s -canonicalize -reconcile-unrealized-casts \
+// RUN: -split-input-file -allow-unregistered-dialect | FileCheck %s \
+// RUN: --check-prefix=CANON
+
+//===----------------------------------------------------------------------===//
+// Basic functionality tests
+//===----------------------------------------------------------------------===//
+
+module {
+ // CHECK-LABEL: func @cast_basic
+ func.func @cast_basic(%arg0: i32) -> f32 {
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} : i32 to f32
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ return %cast : f32
+ }
+
+ // CHECK-LABEL: func @cast_multiple_operands
+ func.func @cast_multiple_operands(%arg0: i32, %arg1: f64) -> (f32, i64) {
+ // CHECK: %{{.*}}:2 = builtin.unrealized_conversion_cast %{{.*}}, %{{.*}} :
+ // CHECK-SAME: i32, f64 to f32, i64
+ %cast:2 = builtin.unrealized_conversion_cast %arg0, %arg1 :
+ i32, f64 to f32, i64
+ return %cast#0, %cast#1 : f32, i64
+ }
+
+ // CHECK-LABEL: func @cast_generation
+ func.func @cast_generation() -> f32 {
+ %unit = arith.constant 0 : i32
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} : i32 to f32
+ %cast = builtin.unrealized_conversion_cast %unit : i32 to f32
+ return %cast : f32
+ }
+
+ // CHECK-LABEL: func @cast_no_results
+ func.func @cast_no_results(%arg0: i32) {
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} : i32 to i32
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to i32
+ return
+ }
+
+ // CHECK-LABEL: func @cast_empty_valid
+ func.func @cast_empty_valid() {
+ %dummy = arith.constant 0 : i32
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} : i32 to i32
+ %cast = builtin.unrealized_conversion_cast %dummy : i32 to i32
+ return
+ }
+
+ // CHECK-LABEL: func @cast_same_type
+ func.func @cast_same_type(%arg0: i32) -> i32 {
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} : i32 to i32
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to i32
+ return %cast : i32
+ }
+
+ // CHECK-LABEL: func @cast_chained
+ func.func @cast_chained(%arg0: i32) -> f64 {
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} : i32 to f32
+ %cast1 = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} : f32 to f64
+ %cast2 = builtin.unrealized_conversion_cast %cast1 : f32 to f64
+ return %cast2 : f64
+ }
+
+ // CHECK-LABEL: func @cast_n_to_m_valid
+ func.func @cast_n_to_m_valid(%arg0: i32, %arg1: f64) -> f32 {
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}}, %{{.*}} :
+ // CHECK-SAME: i32, f64 to f32
+ %cast = builtin.unrealized_conversion_cast %arg0, %arg1 :
+ i32, f64 to f32
+ return %cast : f32
+ }
+
+ // CHECK-LABEL: func @cast_1_to_n_valid
+ func.func @cast_1_to_n_valid(%arg0: i32) -> (f32, f64) {
+ // CHECK: %{{.*}}:2 = builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: i32 to f32, f64
+ %cast:2 = builtin.unrealized_conversion_cast %arg0 :
+ i32 to f32, f64
+ return %cast#0, %cast#1 : f32, f64
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Identity casts (same input/output type)
+//===----------------------------------------------------------------------===//
+
+module {
+ // CHECK-LABEL: func @cast_same_type
+ func.func @cast_same_type() {
+ %dummy = arith.constant 0 : i32
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: i32 to i32
+ %cast1 = builtin.unrealized_conversion_cast %dummy : i32 to i32
+ %cast2 = builtin.unrealized_conversion_cast %dummy : i32 to i32
+ return
+ }
+
+ // CHECK-LABEL: func @cast_multiple_values
+ func.func @cast_multiple_values(%arg0: i32, %arg1: f32) -> (i32, f32) {
+ // CHECK: %{{.*}}:2 = builtin.unrealized_conversion_cast %{{.*}}, %{{.*}} :
+ // CHECK-SAME: i32, f32 to i32, f32
+ %cast:2 = builtin.unrealized_conversion_cast %arg0, %arg1 :
+ i32, f32 to i32, f32
+ return %cast#0, %cast#1 : i32, f32
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Type system boundaries tests
+//===----------------------------------------------------------------------===//
+
+module {
+ // CHECK-LABEL: func @cast_primitive_to_aggregate
+ func.func @cast_primitive_to_aggregate(%arg0: i32) -> tensor<1xi32> {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} : i32 to tensor<1xi32>
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to tensor<1xi32>
+ return %cast : tensor<1xi32>
+ }
+
+ // CHECK-LABEL: func @cast_shaped_types
+ func.func @cast_shaped_types(%arg0: tensor<4x4xf32>) -> memref<4x4xf32> {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: tensor<4x4xf32> to memref<4x4xf32>
+ %cast = builtin.unrealized_conversion_cast %arg0 :
+ tensor<4x4xf32> to memref<4x4xf32>
+ return %cast : memref<4x4xf32>
+ }
+
+ // CHECK-LABEL: func @cast_complex_types
+ func.func @cast_complex_types(%arg0: tensor<4xi32>) -> memref<4xf32> {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: tensor<4xi32> to memref<4xf32>
+ %cast = builtin.unrealized_conversion_cast %arg0 :
+ tensor<4xi32> to memref<4xf32>
+ return %cast : memref<4xf32>
+ }
+
+ // CHECK-LABEL: func @cast_vector_types
+ func.func @cast_vector_types(%arg0: vector<4xi32>) -> vector<4xf32> {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: vector<4xi32> to vector<4xf32>
+ %cast = builtin.unrealized_conversion_cast %arg0 :
+ vector<4xi32> to vector<4xf32>
+ return %cast : vector<4xf32>
+ }
+
+ // CHECK-LABEL: func @cast_index_types
+ func.func @cast_index_types(%arg0: index) -> i64 {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i64
+ %cast = builtin.unrealized_conversion_cast %arg0 : index to i64
+ return %cast : i64
+ }
+
+ // CHECK-LABEL: func @cast_tuple_types
+ func.func @cast_tuple_types(%arg0: tuple<i32, f32>) -> tuple<f64, i64> {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: tuple<i32, f32> to tuple<f64, i64>
+ %cast = builtin.unrealized_conversion_cast %arg0 :
+ tuple<i32, f32> to tuple<f64, i64>
+ return %cast : tuple<f64, i64>
+ }
+
+ // CHECK-LABEL: func @cast_complex_nested
+ func.func @cast_complex_nested(
+ %arg0: tuple<tensor<2xi32>, memref<4xf64>>)
+ -> tuple<memref<2xf32>, tensor<4xi64>> {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: tuple<tensor<2xi32>, memref<4xf64>> to
+ // CHECK-SAME: tuple<memref<2xf32>, tensor<4xi64>>
+ %cast = builtin.unrealized_conversion_cast %arg0 :
+ tuple<tensor<2xi32>, memref<4xf64>> to
+ tuple<memref<2xf32>, tensor<4xi64>>
+ return %cast : tuple<memref<2xf32>, tensor<4xi64>>
+ }
+
+ // CHECK-LABEL: func @cast_unregistered_dialects
+ func.func @cast_unregistered_dialects(
+ %arg0: !custom.type1<"param">) -> !other.type2 {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: !custom.type1<"param"> to !other.type2
+ %cast = builtin.unrealized_conversion_cast %arg0 :
+ !custom.type1<"param"> to !other.type2
+ return %cast : !other.type2
+ }
+
+ // CHECK-LABEL: func @cast_function_types
+ func.func @cast_function_types(
+ %arg0: !mydialect.func<i32 -> f32>)
+ -> !mydialect.func<f64 -> i64> {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: !mydialect.func<i32 -> f32> to !mydialect.func<f64 -> i64>
+ %cast = builtin.unrealized_conversion_cast %arg0 :
+ !mydialect.func<i32 -> f32> to !mydialect.func<f64 -> i64>
+ return %cast : !mydialect.func<f64 -> i64>
+ }
+
+ // CHECK-LABEL: func @cast_variadic_function_types
+ func.func @cast_variadic_function_types(
+ %arg0: !mydialect.func<(i32, ...) -> f32>)
+ -> !mydialect.func<(...) -> ()> {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: !mydialect.func<(i32, ...) -> f32>
+ // CHECK-SAME: to !mydialect.func<(...) -> ()>
+ %cast = builtin.unrealized_conversion_cast %arg0 :
+ !mydialect.func<(i32, ...) -> f32> to
+ !mydialect.func<(...) -> ()>
+ return %cast : !mydialect.func<(...) -> ()>
+ }
+
+ // CHECK-LABEL: func @cast_complex_element_types
+ func.func @cast_complex_element_types(
+ %arg0: complex<f32>) -> complex<f64> {
+ // CHECK: builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: complex<f32> to complex<f64>
+ %cast = builtin.unrealized_conversion_cast %arg0 :
+ complex<f32> to complex<f64>
+ return %cast : complex<f64>
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Pass integration and reconciliation behavior tests
+//===----------------------------------------------------------------------===//
+
+module {
+ // RECONCILE-LABEL: func @cast_chain_elimination
+ func.func @cast_chain_elimination(%arg0: i32) -> i32 {
+ %cast1 = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ %cast2 = builtin.unrealized_conversion_cast %cast1 : f32 to i32
+ // RECONCILE: return %arg0 : i32
+ return %cast2 : i32
+ }
+
+ // RECONCILE-LABEL: func @cast_partial_chain
+ func.func @cast_partial_chain(%arg0: i32) -> f64 {
+ %cast1 = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ %cast2 = builtin.unrealized_conversion_cast %cast1 : f32 to f64
+ return %cast2 : f64
+ }
+
+ // RECONCILE-LABEL: func @cast_no_elimination
+ func.func @cast_no_elimination(%arg0: i32) -> f32 {
+ // RECONCILE: unrealized_conversion_cast
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ return %cast : f32
+ }
+
+ // RECONCILE-LABEL: func @cast_multi_use_no_elimination
+ func.func @cast_multi_use_no_elimination(%arg0: i32) -> (f32, f32) {
+ // RECONCILE: unrealized_conversion_cast
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ return %cast, %cast : f32, f32
+ }
+
+ // RECONCILE-LABEL: func @cast_complex_chain_elimination
+ func.func @cast_complex_chain_elimination(
+ %arg0: i32, %arg1: f32) -> (i32, f32) {
+ %cast1:2 = builtin.unrealized_conversion_cast
+ %arg0, %arg1 : i32, f32 to f64, i64
+ %cast2:2 = builtin.unrealized_conversion_cast
+ %cast1#0, %cast1#1 : f64, i64 to i32, f32
+ // RECONCILE: return %arg0, %arg1 : i32, f32
+ return %cast2#0, %cast2#1 : i32, f32
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Location and attribute preservation tests
+//===----------------------------------------------------------------------===//
+
+module {
+ // CHECK-LABEL: func @cast_with_location
+ func.func @cast_with_location(%arg0: i32) -> f32 {
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: i32 to f32 loc("test_location")
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ loc("test_location")
+ return %cast : f32
+ }
+
+ // CHECK-LABEL: func @cast_nested_locations
+ func.func @cast_nested_locations(%arg0: i32) -> f32 {
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: i32 to f32 loc(callsite("outer" at "inner"))
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ loc(callsite("outer" at "inner"))
+ return %cast : f32
+ }
+
+ // CHECK-LABEL: func @cast_with_attributes
+ func.func @cast_with_attributes(%arg0: i32) -> f32 {
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: i32 to f32 {test_attr = "value"}
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ {test_attr = "value"}
+ return %cast : f32
+ }
+
+ // CHECK-LABEL: func @cast_with_mixed_attributes
+ func.func @cast_with_mixed_attributes(%arg0: i32) -> f32 {
+ // CHECK: %{{.*}} = builtin.unrealized_conversion_cast %{{.*}} :
+ // CHECK-SAME: i32 to f32 {
+ // CHECK-SAME: flag = true, number = 42 : i64, name = "test"}
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ {flag = true, number = 42 : i64, name = "test"}
+ return %cast : f32
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Structural and usage pattern stress tests
+//===----------------------------------------------------------------------===//
+
+module {
+ // CHECK-LABEL: func @cast_many_operands
+ func.func @cast_many_operands(
+ %a: i32, %b: i32, %c: i32, %d: i32, %e: i32) ->
+ (f32, f32, f32, f32, f32) {
+ // CHECK: %{{.*}}:5 = builtin.unrealized_conversion_cast %{{.*}}, %{{.*}},
+ // CHECK-SAME: %{{.*}}, %{{.*}}, %{{.*}} : i32, i32, i32, i32, i32
+ // CHECK-SAME: to f32, f32, f32, f32, f32
+ %cast:5 = builtin.unrealized_conversion_cast
+ %a, %b, %c, %d, %e : i32, i32, i32, i32, i32
+ to f32, f32, f32, f32, f32
+ return %cast#0, %cast#1, %cast#2, %cast#3, %cast#4 :
+ f32, f32, f32, f32, f32
+ }
+
+ // CHECK-LABEL: func @cast_deep_chain
+ func.func @cast_deep_chain(%arg0: i32) -> i64 {
+ // CHECK: i32 to f32
+ %0 = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ // CHECK: f32 to f64
+ %1 = builtin.unrealized_conversion_cast %0 : f32 to f64
+ // CHECK: f64 to i8
+ %2 = builtin.unrealized_conversion_cast %1 : f64 to i8
+ // CHECK: i8 to i16
+ %3 = builtin.unrealized_conversion_cast %2 : i8 to i16
+ // CHECK: i16 to i64
+ %4 = builtin.unrealized_conversion_cast %3 : i16 to i64
+ return %4 : i64
+ }
+
+ // CHECK-LABEL: func @cast_wide_fanout
+ func.func @cast_wide_fanout(%arg0: i32) ->
+ (f32, f32, f32, f32, f32, f32, f32, f32) {
+ // CHECK: i32 to f32
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ return %cast, %cast, %cast, %cast,
+ %cast, %cast, %cast, %cast :
+ f32, f32, f32, f32, f32, f32, f32, f32
+ }
+
+ // CHECK-LABEL: func @cast_diamond_pattern
+ func.func @cast_diamond_pattern(%arg0: i32) -> f64 {
+ // CHECK: i32 to f32
+ %cast1 = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ // CHECK: f32 to i64
+ %cast2 = builtin.unrealized_conversion_cast %cast1 : f32 to i64
+ // CHECK: f32 to i16
+ %cast3 = builtin.unrealized_conversion_cast %cast1 : f32 to i16
+ // CHECK: i64, i16 to f64
+ %cast4 = builtin.unrealized_conversion_cast
+ %cast2, %cast3 : i64, i16 to f64
+ return %cast4 : f64
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Integration with control flow and region-based operations
+//===----------------------------------------------------------------------===//
+
+module {
+ // CHECK-LABEL: func @cast_in_control_flow
+ func.func @cast_in_control_flow(%cond: i1, %arg0: i32) -> f32 {
+ cf.cond_br %cond, ^bb1, ^bb2
+ ^bb1:
+ // CHECK: i32 to f32
+ %cast1 = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ cf.br ^bb3(%cast1 : f32)
+ ^bb2:
+ // CHECK: i32 to f32
+ %cast2 = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ cf.br ^bb3(%cast2 : f32)
+ ^bb3(%result: f32):
+ return %result : f32
+ }
+
+ // CHECK-LABEL: func @cast_with_regions
+ func.func @cast_with_regions(%arg0: i32) -> f32 {
+ %result = scf.execute_region -> f32 {
+ // CHECK: i32 to f32
+ %cast = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ scf.yield %cast : f32
+ }
+ return %result : f32
+ }
+
+ // CHECK-LABEL: func @cast_in_loops
+ func.func @cast_in_loops(%arg0: i32, %ub: index) -> f32 {
+ %c0 = arith.constant 0 : index
+ %c1 = arith.constant 1 : index
+ // CHECK: i32 to f32
+ %init = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ %result = scf.for %i = %c0 to %ub step %c1
+ iter_args(%iter = %init) -> (f32) {
+ // CHECK: f32 to i32
+ %temp = builtin.unrealized_conversion_cast %iter : f32 to i32
+ // CHECK: i32 to f32
+ %cast = builtin.unrealized_conversion_cast %temp : i32 to f32
+ scf.yield %cast : f32
+ }
+ return %result : f32
+ }
+
+ // CHECK-LABEL: func @cast_in_nested_regions
+ func.func @cast_in_nested_regions(%arg0: i32, %cond: i1) -> f32 {
+ %result = scf.execute_region -> f32 {
+ %inner_result = scf.if %cond -> f32 {
+ // CHECK: i32 to f32
+ %cast1 = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ scf.yield %cast1 : f32
+ } else {
+ // CHECK: i32 to f32
+ %cast2 = builtin.unrealized_conversion_cast %arg0 : i32 to f32
+ scf.yield %cast2 : f32
+ }
+ scf.yield %inner_result : f32
+ }
+ return %result : f32
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Memory types and dimensionality boundaries tests
+//===----------------------------------------------------------------------===//
+
+module {
+ // CHECK-LABEL: func @cast_large_types
+ func.func @cast_large_types(
+ %arg0: tensor<1024x1024x1024xf32>
+ ) -> memref<1024x1024x1024xf64> {
+ // CHECK: tensor<1024x1024x1024xf32> to memref<1024x1024x1024xf64>
+ %cast = builtin.unrealized_conversion_cast %arg0
+ : tensor<1024x1024x1024xf32> to memref<1024x1024x1024xf64>
+ return %cast : memref<1024x1024x1024xf64>
+ }
+
+ // CHECK-LABEL: func @cast_dynamic_shapes
+ func.func @cast_dynamic_shapes(
+ %arg0: tensor<?x?xf32>
+ ) -> memref<?x?xf64> {
+ // CHECK: tensor<?x?xf32> to memref<?x?xf64>
+ %cast = builtin.unrealized_conversion_cast %arg0
+ : tensor<?x?xf32> to memref<?x?xf64>
+ return %cast : memref<?x?xf64>
+ }
+
+ // CHECK-LABEL: func @cast_mixed_dynamic_static
+ func.func @cast_mixed_dynamic_static(
+ %arg0: tensor<?x4x?xf32>
+ ) -> memref<8x?x16xf64> {
+ // CHECK: tensor<?x4x?xf32> to memref<8x?x16xf64>
+ %cast = builtin.unrealized_conversion_cast %arg0
+ : tensor<?x4x?xf32> to memref<8x?x16xf64>
+ return %cast : memref<8x?x16xf64>
+ }
+
+ // CHECK-LABEL: func @cast_strided_memrefs
+ func.func @cast_strided_memrefs(
+ %arg0: memref<4x4xf32, strided<[4, 1]>>
+ ) -> memref<4x4xf64, strided<[8, 2]>> {
+ // CHECK: memref<4x4xf32, strided<[4, 1]>> to
+ // CHECK-SAME: memref<4x4xf64, strided<[8, 2]>>
+ %cast = builtin.unrealized_conversion_cast %arg0
+ : memref<4x4xf32, strided<[4, 1]>>
+ to memref<4x4xf64, strided<[8, 2]>>
+ return %cast : memref<4x4xf64, strided<[8, 2]>>
+ }
+
+ // CHECK-LABEL: func @cast_unranked_tensors
+ func.func @cast_unranked_tensors(
+ %arg0: tensor<*xf32>
+ ) -> tensor<*xf64> {
+ // CHECK: tensor<*xf32> to tensor<*xf64>
+ %cast = builtin.unrealized_conversion_cast %arg0
+ : tensor<*xf32> to tensor<*xf64>
+ return %cast : tensor<*xf64>
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Canonicalization interaction tests
+//===----------------------------------------------------------------------===//
+
+module {
+ // CANON-LABEL: func @cast_with_canonicalization
+ func.func @cast_with_canonicalization(%arg0: i32) -> i32 {
+ %c1 = arith.constant 1 : i32
+ %add = arith.addi %arg0, %c1 : i32
+ %cast1 = builtin.unrealized_conversion_cast %add : i32 to f32
+ %cast2 = builtin.unrealized_conversion_cast %cast1 : f32 to i32
+ return %cast2 : i32
+ }
+
+ // CANON-LABEL: func @cast_constant_folding_interaction
+ func.func @cast_constant_folding_interaction() -> f64 {
+ %c0 = arith.constant 0 : i32
+ %c1 = arith.constant 1 : i32
+ %add = arith.addi %c0, %c1 : i32
+ %cast1 = builti...
[truncated]
|
126bad1
to
8163bf4
Compare
Adds a suite of IR tests for the unrealized_conversion_cast operation, covering a wide range of type conversion scenarios and edge cases: - Basic functionality - Identity casts (input and output types are the same) - Type system boundaries (e.g., shaped, tuple, and custom types) - Pass integration and reconciliation behavior - Location and attribute preservation - Structural, usage pattern and compilation-time stress (e.g., fan-out, deep chains) - Integration with control flow and region-based operations - Memory types and dimensionality boundaries (e.g., dynamic shapes, unranked tensors) - Canonicalization interaction (e.g., with constant folding, CSE, DCE) - Complex and nested type patterns - Edge cases and boundary conditions (e.g., bitwidths, scalable vectors) These tests help guard against regressions and provide a robust reference for dialect authors using unrealized_conversion_cast in type conversion scenarios across dialect boundaries.
8163bf4
to
c5a263b
Compare
[MLIR][Test] Extend coverage of unrealized_conversion_cast operation
Adds a suite of IR tests for the unrealized_conversion_cast operation, covering a wide range of type conversion scenarios and edge cases:
These tests help guard against regressions and provide a robust reference for dialect authors using unrealized_conversion_cast in type conversion scenarios across dialect boundaries.