diff --git a/tensorflow/compiler/mlir/lite/ir/tfl_ops.td b/tensorflow/compiler/mlir/lite/ir/tfl_ops.td index 34920cd1792..536960e347d 100644 --- a/tensorflow/compiler/mlir/lite/ir/tfl_ops.td +++ b/tensorflow/compiler/mlir/lite/ir/tfl_ops.td @@ -212,11 +212,20 @@ class TFL_OperandIsRankedAndHasDimPred : And<[ CPred<"$_op.getOperand(" # n # ").getType().cast().getRank() > " # dim>]>; +// Returns true if the n-th operand is ranked and has a dimension length = size +// at the rank dim. class TFL_OperandDimEquals : And<[ TFL_OperandIsRankedAndHasDimPred, CPred<"$_op.getOperand(" # n # ").getType().cast()" ".getShape()[" # dim # " ] == " # size>]>; +// Returns true if the n-th operand is ranked and has a dimension length <= +// size at the rank dim. +class TFL_OperandDimIsAtMost : And<[ + TFL_OperandIsRankedAndHasDimPred, + CPred<"$_op.getOperand(" # n # ").getType().cast()" + ".getShape()[" # dim # " ] <= " # size>]>; + // Returns true if the n-th operand has unknown rank or at least rank m. class TFL_OperandHasAtleastRank : PredOpTrait<"operand " # n # " is " # m # "-D", @@ -2267,6 +2276,9 @@ def TFL_PadOp : TFL_Op<"pad", [ TFL_OperandHasRankAtMost<0, 4>, TFL_OperandHasRank<1, 2>, TFL_OperandRankEquals1DimOfOperand<0, 1>, + PredOpTrait<"the first dim size of the padding argument must be at most 4", + Or<[TFL_OperandIsUnrankedPred<1>, + TFL_OperandDimIsAtMost<1, 0, 4>]>>, TFL_GpuTargetOp]> { let summary = "Padding operator"; @@ -2312,6 +2324,9 @@ def TFL_PadV2Op : TFL_Op<"padv2", [ TFL_OperandHasRank<1, 2>, TFL_OperandHasRank<2, 0>, TFL_OperandRankEquals1DimOfOperand<0, 1>, + PredOpTrait<"the first dim size of the padding argument must be at most 4", + Or<[TFL_OperandIsUnrankedPred<1>, + TFL_OperandDimIsAtMost<1, 0, 4>]>>, PredOpTrait<"input and constant value operands must have same element type", TFL_TCopVTEtAreSameAt<0, 2>>]> { let summary = "Padding operator v2"; diff --git a/tensorflow/compiler/mlir/lite/tests/ops.mlir b/tensorflow/compiler/mlir/lite/tests/ops.mlir index ef9d86f242b..6ab3aa250af 100644 --- a/tensorflow/compiler/mlir/lite/tests/ops.mlir +++ b/tensorflow/compiler/mlir/lite/tests/ops.mlir @@ -923,6 +923,27 @@ func @testPadWithInvalidPaddingsRank(tensor<2x1x3xf32>, tensor<1x3x2xi32>) -> te // ----- +func @testPadUnknownPaddings(tensor<2x1x3xf32>, tensor<*xi32>) -> tensor { +^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<*xi32>): + %0 = "tfl.pad"(%arg0, %arg1) : (tensor<2x1x3xf32>, tensor<*xi32>) -> tensor + return %0#0 : tensor + + // CHECK-LABEL: testPadUnknownPaddings + // CHECK: "tfl.pad"(%arg0, %arg1) : (tensor<2x1x3xf32>, tensor<*xi32>) -> tensor + // CHECK: return +} + +// ----- + +func @testPadUnsupportedPaddings(tensor<*xf32>, tensor<5x3xi32>) -> tensor { +^bb0(%arg0: tensor<*xf32>, %arg1: tensor<5x3xi32>): + // expected-error @+1 {{'tfl.pad' op failed to verify that the first dim size of the padding argument must be at most 4}} + %0 = "tfl.pad"(%arg0, %arg1) : (tensor<*xf32>, tensor<5x3xi32>) -> tensor + return %0#0 : tensor +} + +// ----- + // CHECK-LABEL: testPadQuantizedU8 func @testPadQuantizedU8(%arg0: tensor<2x1x3x!quant.uniform>, %arg1: tensor<3x2xi32>) -> tensor> { // CHECK: "tfl.pad"(%arg0, %arg1) @@ -993,6 +1014,29 @@ func @testPadV2WithInvalidConstantScalar(tensor<2x1x3xf32>, tensor<3x2xi32>) -> // ----- +func @testPadV2UnknownPaddings(tensor<2x1x3xf32>, tensor<*xi32>) -> tensor { +^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<*xi32>): + %cst = constant dense<2.0> : tensor + %0 = "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<2x1x3xf32>, tensor<*xi32>, tensor) -> tensor + return %0#0 : tensor + + // CHECK-LABEL: testPadV2UnknownPaddings + // CHECK: "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<2x1x3xf32>, tensor<*xi32>, tensor) -> tensor + // CHECK: return +} + +// ----- + +func @testPadV2UnsupportedPaddings(tensor<*xf32>, tensor<5x3xi32>) -> tensor { +^bb0(%arg0: tensor<*xf32>, %arg1: tensor<5x3xi32>): + %cst = constant dense<2.0> : tensor + // expected-error @+1 {{'tfl.padv2' op failed to verify that the first dim size of the padding argument must be at most 4}} + %0 = "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<*xf32>, tensor<5x3xi32>, tensor) -> tensor + return %0#0 : tensor +} + +// ----- + func @packQuantizedU8(%arg0: tensor<2x!quant.uniform>, %arg1: tensor<2x!quant.uniform>) -> tensor<2x2x!quant.uniform> { // CHECK: "tfl.pack"(%arg0, %arg1) {axis = 0 : i32, values_count = 2 : i32} %0 = "tfl.pack"(%arg0, %arg1) {axis = 0 : i32, values_count = 2 : i32} : (tensor<2x!quant.uniform>, tensor<2x!quant.uniform>) -> tensor<2x2x!quant.uniform>