[Mlir-commits] [mlir] a7bf938 - [mlir][tosa] Fix conv/depthwise conv padding for quantized values
Rob Suderman
llvmlistbot at llvm.org
Tue Aug 24 18:14:18 PDT 2021
Author: Rob Suderman
Date: 2021-08-24T18:13:22-07:00
New Revision: a7bf93807b403fdd1af1c7270a20c4849a739be4
URL: https://github.com/llvm/llvm-project/commit/a7bf93807b403fdd1af1c7270a20c4849a739be4
DIFF: https://github.com/llvm/llvm-project/commit/a7bf93807b403fdd1af1c7270a20c4849a739be4.diff
LOG: [mlir][tosa] Fix conv/depthwise conv padding for quantized values
When padding quantized operations, the padding needs to equal the zero point
of the input value. Corrected the pass to change the padding value if quantized.
Reviewed By: NatashaKnk
Differential Revision: https://reviews.llvm.org/D108440
Added:
Modified:
mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
index cfd1696d55d15..a670ace340621 100644
--- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
+++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
@@ -911,10 +911,33 @@ class ConvConverter : public OpConversionPattern<tosa::Conv2DOp> {
return rewriter.notifyMatchFailure(op,
"tosa.conv ops require static shapes");
+ if (inputETy.isUnsignedInteger())
+ return rewriter.notifyMatchFailure(
+ op, "tosa.conv ops does not support unsigned integer input");
+
auto weightShape = weightTy.getShape();
// Apply padding as necessary.
Attribute zeroAttr = rewriter.getZeroAttr(inputETy);
+ if (isQuantized) {
+ auto quantizationInfo =
+ op->getAttr("quantization_info").cast<tosa::ConvOpQuantizationAttr>();
+ auto iZp = quantizationInfo.input_zp().getValue().getSExtValue();
+
+ int64_t intMin =
+ APInt::getSignedMinValue(inputETy.getIntOrFloatBitWidth())
+ .getSExtValue();
+ int64_t intMax =
+ APInt::getSignedMaxValue(inputETy.getIntOrFloatBitWidth())
+ .getSExtValue();
+
+ if (iZp < intMin || iZp > intMax)
+ return rewriter.notifyMatchFailure(
+ op, "tosa.conv op quantization has zp outside of input range");
+
+ zeroAttr = rewriter.getIntegerAttr(inputETy, iZp);
+ }
+
llvm::SmallVector<int64_t> pad;
pad.resize(2, 0);
getValuesFromIntArrayAttribute(padAttr, pad);
@@ -1038,6 +1061,26 @@ class DepthwiseConvConverter
// Apply padding as necessary.
Attribute zeroAttr = rewriter.getZeroAttr(inputETy);
+ if (isQuantized) {
+ auto quantizationInfo =
+ op->getAttr("quantization_info").cast<tosa::ConvOpQuantizationAttr>();
+ auto iZp = quantizationInfo.input_zp().getValue().getSExtValue();
+
+ int64_t intMin =
+ APInt::getSignedMinValue(inputETy.getIntOrFloatBitWidth())
+ .getSExtValue();
+ int64_t intMax =
+ APInt::getSignedMaxValue(inputETy.getIntOrFloatBitWidth())
+ .getSExtValue();
+
+ if (iZp < intMin || iZp > intMax)
+ return rewriter.notifyMatchFailure(
+ op, "tosa.depthwise_conv op quantization has zp outside of input "
+ "range");
+
+ zeroAttr = rewriter.getIntegerAttr(inputETy, iZp);
+ }
+
llvm::SmallVector<int64_t> pad;
pad.resize(2, 0);
getValuesFromIntArrayAttribute(padAttr, pad);
diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir
index 68f56bd84cc9c..908868e076e59 100644
--- a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir
+++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir
@@ -1274,7 +1274,9 @@ func @conv2d_f32(%input: tensor<1x49x42x27xf32>, %weights: tensor<28x3x3x27xf32>
// CHECK-LABEL: @conv2d_padded_f32
func @conv2d_padded_f32(%input: tensor<1x47x40x28xf32>, %weights: tensor<28x3x3x28xf32>, %bias: tensor<28xf32>) -> () {
+ // CHECK: %[[C0:.+]] = constant 0
// CHECK: linalg.pad_tensor %arg0 low[0, 1, 1, 0] high[0, 1, 1, 0]
+ // CHECK: linalg.yield %[[C0]]
// CHECK: linalg.conv_2d_nhwc_hwcf
%0 = "tosa.conv2d"(%input, %weights, %bias) {pad = [1, 1, 1, 1], stride = [1, 1], dilation = [2, 1]} : (tensor<1x47x40x28xf32>, tensor<28x3x3x28xf32>, tensor<28xf32>) -> (tensor<1x45x40x28xf32>)
return
@@ -1284,8 +1286,11 @@ func @conv2d_padded_f32(%input: tensor<1x47x40x28xf32>, %weights: tensor<28x3x3x
// CHECK-LABEL: @conv2d_quant
func @conv2d_quant(%arg0 : tensor<1x12x12x1xi8>, %arg1 : tensor<1024x3x3x1xi8>, %arg2 : tensor<1024xi32>) -> () {
+ // CHECK: %[[C22:.+]] = constant -22
+ // CHECK: linalg.pad_tensor %arg0 low[0, 1, 1, 0] high[0, 1, 1, 0]
+ // CHECK: linalg.yield %[[C22]]
// CHECK: linalg.conv_2d_nhwc_hwcf_q
- %0 = "tosa.conv2d"(%arg0, %arg1, %arg2) {dilation = [1, 1], pad = [0, 0, 0, 0], quantization_info = {input_zp = -128 : i32, weight_zp = 42 : i32}, stride = [1, 1]} : (tensor<1x12x12x1xi8>, tensor<1024x3x3x1xi8>, tensor<1024xi32>) -> tensor<1x10x10x1024xi32>
+ %0 = "tosa.conv2d"(%arg0, %arg1, %arg2) {dilation = [1, 1], pad = [1, 1, 1, 1], quantization_info = {input_zp = -22 : i32, weight_zp = 42 : i32}, stride = [1, 1]} : (tensor<1x12x12x1xi8>, tensor<1024x3x3x1xi8>, tensor<1024xi32>) -> tensor<1x12x12x1024xi32>
return
}
@@ -1322,7 +1327,7 @@ func @depthwise_conv_strides(%arg0 : tensor<1x11x9x3xf32>, %arg1 : tensor<3x1x3x
// CHECK: } -> tensor<1x5x5x33xf32>
// CHECK: [[DBIAS:%.+]] = linalg.tensor_expand_shape [[BIAS]] {{\[}}[0], [1], [2], [3, 4]]
// CHECK: [[DEPTH:%.+]] = linalg.depthwise_conv2D_nhwc {dilations = dense<1> : tensor<2xi64>, strides = dense<2> : tensor<2xi64>} ins(%arg0, %arg1 : tensor<1x11x9x3xf32>, tensor<3x1x3x11xf32>) outs([[DBIAS]] : tensor<1x5x5x3x11xf32>)
- // CHECK: linalg.tensor_collapse_shape %3 {{\[}}[0], [1], [2], [3, 4]]
+ // CHECK: linalg.tensor_collapse_shape [[DEPTH]] {{\[}}[0], [1], [2], [3, 4]]
%2 = "tosa.depthwise_conv2d"(%arg0, %arg1, %arg2) { pad = [0, 0, 0, 0], stride = [2, 2], dilation = [1, 1] } : (tensor<1x11x9x3xf32>, tensor<3x1x3x11xf32>, tensor<33xf32>) -> (tensor<1x5x5x33xf32>)
return
}
@@ -1334,17 +1339,21 @@ func @depthwise_conv_strides(%arg0 : tensor<1x11x9x3xf32>, %arg1 : tensor<3x1x3x
// CHECK-LABEL: @depthwise_conv_quant
func @depthwise_conv_quant(%arg0 : tensor<1x12x12x4xi8>, %arg1 : tensor<3x3x4x128xi8>, %arg2 : tensor<512xi32>) -> () {
- // CHECK: [[INIT:%.+]] = linalg.init_tensor [1, 10, 10, 512]
- // CHECK: [[BIAS:%.+]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]]], iterator_types = ["parallel", "parallel", "parallel", "parallel"]} ins(%arg2 : tensor<512xi32>) outs([[INIT]] : tensor<1x10x10x512xi32>) {
+ // CHECK: %[[PADV:.+]] = constant -128
+ // CHECK: %[[PAD:.+]] = linalg.pad_tensor %arg0 low[0, 1, 1, 0] high[0, 1, 1, 0]
+ // CHECK: linalg.yield %[[PADV]]
+
+ // CHECK: [[INIT:%.+]] = linalg.init_tensor [1, 12, 12, 512]
+ // CHECK: [[BIAS:%.+]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]]], iterator_types = ["parallel", "parallel", "parallel", "parallel"]} ins(%arg2 : tensor<512xi32>) outs([[INIT]] : tensor<1x12x12x512xi32>) {
// CHECK: ^bb0(%arg3: i32, %arg4: i32): // no predecessors
// CHECK: linalg.yield %arg3 : i32
- // CHECK: } -> tensor<1x10x10x512xi32>
- // CHECK: [[DBIAS:%.+]] = linalg.tensor_expand_shape [[BIAS]] {{\[}}[0], [1], [2], [3, 4]]
+ // CHECK: } -> tensor<1x12x12x512xi32>
+ // CHECK: %[[DBIAS:.+]] = linalg.tensor_expand_shape [[BIAS]] {{\[}}[0], [1], [2], [3, 4]]
// CHECK: %[[C128:.+]] = constant -128
// CHECK: %[[C42:.+]] = constant 42
- // CHECK: [[DEPTH:%.+]] = linalg.depthwise_conv2D_nhwc_q {dilations = dense<1> : tensor<2xi64>, strides = dense<1> : tensor<2xi64>} ins(%arg0, %arg1, %[[C128]], %[[C42]] : tensor<1x12x12x4xi8>, tensor<3x3x4x128xi8>, i32, i32) outs([[DBIAS]] : tensor<1x10x10x4x128xi32>)
- // CHECK: linalg.tensor_collapse_shape %3 {{\[}}[0], [1], [2], [3, 4]]
- %0 = "tosa.depthwise_conv2d"(%arg0, %arg1, %arg2) {pad = [0, 0, 0, 0], quantization_info = {input_zp = -128 : i32, weight_zp = 42 : i32}, stride = [1, 1], dilation = [1, 1] } : (tensor<1x12x12x4xi8>, tensor<3x3x4x128xi8>, tensor<512xi32>) -> tensor<1x10x10x512xi32>
+ // CHECK: %[[DEPTH:.+]] = linalg.depthwise_conv2D_nhwc_q {dilations = dense<1> : tensor<2xi64>, strides = dense<1> : tensor<2xi64>} ins(%[[PAD]], %arg1, %[[C128]], %[[C42]] : tensor<1x14x14x4xi8>, tensor<3x3x4x128xi8>, i32, i32) outs(%[[DBIAS]] : tensor<1x12x12x4x128xi32>)
+ // CHECK: linalg.tensor_collapse_shape %[[DEPTH]] {{\[}}[0], [1], [2], [3, 4]]
+ %0 = "tosa.depthwise_conv2d"(%arg0, %arg1, %arg2) {pad = [1, 1, 1, 1], quantization_info = {input_zp = -128 : i32, weight_zp = 42 : i32}, stride = [1, 1], dilation = [1, 1] } : (tensor<1x12x12x4xi8>, tensor<3x3x4x128xi8>, tensor<512xi32>) -> tensor<1x12x12x512xi32>
return
}
More information about the Mlir-commits
mailing list