Fix `stablehlo.convolution` padding with `complex<f32>` (#14123)
Existing padding insertion is not compatible with complex types. Fix to
know how to create a complex type.
diff --git a/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgConvolution.cpp b/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgConvolution.cpp
index d1a1fe7..62cd0c9 100644
--- a/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgConvolution.cpp
+++ b/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgConvolution.cpp
@@ -57,9 +57,20 @@
IntegerType indexType = rewriter.getIntegerType(64);
auto attrType = RankedTensorType::get({rank}, indexType);
- Value zero = rewriter.create<arith::ConstantOp>(
- loc, rewriter.getZeroAttr(
- RankedTensorType::get({}, inputType.getElementType())));
+
+ Value zero;
+ if (auto complexType = dyn_cast<ComplexType>(inputType.getElementType())) {
+ auto zeroElement = rewriter.getZeroAttr(complexType.getElementType());
+ auto zeroAttr = rewriter.getArrayAttr({zeroElement, zeroElement});
+ zero = rewriter.create<complex::ConstantOp>(loc, complexType, zeroAttr);
+ zero = rewriter.create<tensor::FromElementsOp>(
+ loc, RankedTensorType::get({}, complexType), zero);
+ } else {
+ zero = rewriter.create<arith::ConstantOp>(
+ loc, rewriter.getZeroAttr(
+ RankedTensorType::get({}, inputType.getElementType())));
+ }
+
return rewriter.create<mlir::stablehlo::PadOp>(
loc, input, zero, DenseIntElementsAttr::get(attrType, padLow),
DenseIntElementsAttr::get(attrType, padHigh),
diff --git a/compiler/src/iree/compiler/InputConversion/StableHLO/test/stablehlo_to_linalg_convolution.mlir b/compiler/src/iree/compiler/InputConversion/StableHLO/test/stablehlo_to_linalg_convolution.mlir
index 1a6936b..2b20586 100644
--- a/compiler/src/iree/compiler/InputConversion/StableHLO/test/stablehlo_to_linalg_convolution.mlir
+++ b/compiler/src/iree/compiler/InputConversion/StableHLO/test/stablehlo_to_linalg_convolution.mlir
@@ -133,6 +133,38 @@
// -----
+// CHECK-LABEL: func @conv_transpose_complex_2d
+// CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]*]]
+// CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]*]]
+func.func @conv_transpose_complex_2d(%arg0: tensor<2x9x10x3xcomplex<f32>>,
+ %arg1: tensor<4x4x3x3xcomplex<f32>>)
+ -> tensor<2x15x25x3xcomplex<f32>> {
+ %0 = stablehlo.convolution(%arg0, %arg1)
+ dim_numbers = [b, 0, 1, f]x[0, 1, i, o]->[b, 0, 1, f],
+ window = {stride = [1, 1], pad = [[6, 6], [6, 6]],
+ lhs_dilate = [1, 2], rhs_dilate = [2, 2]}
+ {
+ batch_group_count = 1 : i64,
+ feature_group_count = 1 : i64,
+ precision_config = [#stablehlo<precision DEFAULT>,
+ #stablehlo<precision DEFAULT>]
+ } : (tensor<2x9x10x3xcomplex<f32>>, tensor<4x4x3x3xcomplex<f32>>) -> tensor<2x15x25x3xcomplex<f32>>
+ return %0 : tensor<2x15x25x3xcomplex<f32>>
+}
+// CHECK: %[[ZERO:.+]] = complex.constant [0.000000e+00 : f32, 0.000000e+00 : f32] : complex<f32>
+// CHECK: %[[INIT:.+]] = tensor.empty()
+// CHECK: %[[FILL:.+]] = linalg.fill ins(%[[ZERO]]{{.*}}outs(%[[INIT]]
+// CHECK: %[[LHS_INIT:.+]] = tensor.empty()
+// CHECK: %[[LHS_FILL:.+]] = linalg.fill ins(%[[ZERO]]{{.*}}outs(%[[LHS_INIT]]
+// CHECK: %[[LHS_PAD:.+]] = tensor.insert_slice %[[ARG0]] into %[[LHS_FILL]][0, 6, 6, 0] [2, 9, 10, 3] [1, 1, 2, 1] : tensor<2x9x10x3xcomplex<f32>> into tensor<2x21x31x3xcomplex<f32>>
+// CHECK: linalg.conv_2d_nhwc_hwcf
+// CHECK-SAME: {dilations = dense<2> : tensor<2xi64>
+// CHECK-SAME: strides = dense<1> : tensor<2xi64>}
+// CHECK-SAME: ins(%[[LHS_PAD]], %[[ARG1]] : tensor<2x21x31x3xcomplex<f32>>, tensor<4x4x3x3xcomplex<f32>>)
+// CHECK-SAME: outs(%[[FILL]] : tensor<2x15x25x3xcomplex<f32>>) -> tensor<2x15x25x3xcomplex<f32>>
+
+// -----
+
// Just check that this lowers successfully.
// CHECK-LABEL: func @conv_different_batch_dim_in_out
func.func @conv_different_batch_dim_in_out(%arg0: tensor<1x1x1xf64>,