diff --git a/tools/mlir/fix_td.sh b/tools/mlir/fix_td.sh new file mode 100644 index 000000000..874204c74 --- /dev/null +++ b/tools/mlir/fix_td.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# This dirty script eat td files :P +# https://github.com/tensorflow/tensorflow/tree/master/tensorflow/compiler/mlir/tensorflow/ir + +sed -i '/let hasCanonicalizer = 1;/d' *.td +sed -i '/let hasFolder = 1;/d' *.td +sed -i '/StringRef GetOptimalLayout(const RuntimeDevices& devices);/d' *.td +sed -i '/LogicalResult UpdateDataFormat(StringRef data_format);/d' *.td +sed -i '/LogicalResult FoldOperandsPermutation(ArrayRef permutation);/d' *.td diff --git a/tools/mlir/mlir2ncnn.cpp b/tools/mlir/mlir2ncnn.cpp index 73de38b37..d08dc669d 100644 --- a/tools/mlir/mlir2ncnn.cpp +++ b/tools/mlir/mlir2ncnn.cpp @@ -48,12 +48,14 @@ #include #include #include +#include #include #include #include #include #include "tf_attributes.h" +#include "tf_side_effects.h" #include "tf_traits.h" namespace mlir { @@ -384,6 +386,30 @@ LogicalResult ConstOp::inferReturnTypes( "constant vector/tensor"); } +Region& WhileRegionOp::getLoopBody() +{ + return body(); +} + +bool WhileRegionOp::isDefinedOutsideOfLoop(Value value) +{ + // If the Op defining the value exists and the defining op is outside the + // scope of this WhileRegion, then we can infer that its defined outside. + // The defining Op is outside the scope of this WhileRegion if this + // WhileRegionOp is not an ancestor of the defining op in the parent chain. + Operation* def_op = value.getDefiningOp(); + return def_op && !getOperation()->isAncestor(def_op); +} + +LogicalResult WhileRegionOp::moveOutOfLoop( + llvm::ArrayRef ops) +{ + // Move the hoisted value to just before the while. + Operation* while_op = this->getOperation(); + for (auto op : ops) op->moveBefore(while_op); + return success(); +} + } // namespace TF } // namespace mlir diff --git a/tools/mlir/tf_generated_ops.td b/tools/mlir/tf_generated_ops.td index e6555dcfd..5310df73f 100644 --- a/tools/mlir/tf_generated_ops.td +++ b/tools/mlir/tf_generated_ops.td @@ -52,15 +52,12 @@ an output element, this operation computes \\(y = |x|\\). def TF_AcosOp : TF_Op<"Acos", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Computes acos of x element-wise."; - let description = [{ - }]; - let arguments = (ins - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$x + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$x ); let results = (outs - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$y + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$y ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; @@ -110,7 +107,6 @@ def TF_AddOp : TF_Op<"Add", [NoSideEffect, ResultsBroadcastableShape, TF_LayoutA TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_AddNOp : TF_Op<"AddN", [Commutative, NoSideEffect]> { @@ -136,7 +132,6 @@ Inputs must be of same size and shape. TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; TF_DerivedOperandSizeAttr N = TF_DerivedOperandSizeAttr<0>; -// let hasFolder = 1; } def TF_AddV2Op : TF_Op<"AddV2", [Commutative, NoSideEffect, ResultsBroadcastableShape, TF_LayoutAgnostic]>, @@ -159,9 +154,82 @@ def TF_AddV2Op : TF_Op<"AddV2", [Commutative, NoSideEffect, ResultsBroadcastable TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; -// let hasFolder = 1; +} + +def TF_AdjustContrastv2Op : TF_Op<"AdjustContrastv2", [NoSideEffect]> { + let summary = "Adjust the contrast of one or more images."; + + let description = [{ +`images` is a tensor of at least 3 dimensions. The last 3 dimensions are +interpreted as `[height, width, channels]`. The other dimensions only +represent a collection of images, such as `[batch, height, width, channels].` + +Contrast is adjusted independently for each channel of each image. + +For each channel, the Op first computes the mean of the image pixels in the +channel and then adjusts each component of each pixel to +`(x - mean) * contrast_factor + mean`. + }]; + + let arguments = (ins + TensorOf<[F16, F32]>:$images, + F32Tensor:$contrast_factor + ); + + let results = (outs + TensorOf<[F16, F32]>:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + +def TF_AdjustHueOp : TF_Op<"AdjustHue", [NoSideEffect]> { + let summary = "Adjust the hue of one or more images."; + + let description = [{ +`images` is a tensor of at least 3 dimensions. The last dimension is +interpreted as channels, and must be three. + +The input image is considered in the RGB colorspace. Conceptually, the RGB +colors are first mapped into HSV. A delta is then applied all the hue values, +and then remapped back to RGB colorspace. + }]; + + let arguments = (ins + TensorOf<[F16, F32]>:$images, + F32Tensor:$delta + ); + + let results = (outs + TensorOf<[F16, F32]>:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + +def TF_AdjustSaturationOp : TF_Op<"AdjustSaturation", [NoSideEffect]> { + let summary = "Adjust the saturation of one or more images."; + + let description = [{ +`images` is a tensor of at least 3 dimensions. The last dimension is +interpreted as channels, and must be three. + +The input image is considered in the RGB colorspace. Conceptually, the RGB +colors are first mapped into HSV. A scale is then applied all the saturation +values, and then remapped back to RGB colorspace. + }]; + + let arguments = (ins + TensorOf<[F16, F32]>:$images, + F32Tensor:$scale + ); + + let results = (outs + TensorOf<[F16, F32]>:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } def TF_AllOp : TF_Op<"All", [NoSideEffect]> { @@ -296,9 +364,6 @@ retained with length 1. def TF_ApproximateEqualOp : TF_Op<"ApproximateEqual", [Commutative, NoSideEffect]> { let summary = "Returns the truth value of abs(x-y) < tolerance element-wise."; - let description = [{ - }]; - let arguments = (ins TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$x, TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$y, @@ -436,11 +501,11 @@ tf.math.asin(y) # [1.047, 0.785] = x }]; let arguments = (ins - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$x + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$x ); let results = (outs - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$y + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$y ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; @@ -490,7 +555,6 @@ If `condition` evaluates to false, print the list of tensors in `data`. TF_DerivedOperandTypeListAttr T = TF_DerivedOperandTypeListAttr<1>; -// let hasCanonicalizer = 1; } def TF_AssignAddVariableOp : TF_Op<"AssignAddVariableOp", []> { @@ -569,11 +633,11 @@ tf.math.atan(y) # [1.047, 0.785] = x }]; let arguments = (ins - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$x + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$x ); let results = (outs - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$y + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$y ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; @@ -656,12 +720,29 @@ window in `value`. TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } +def TF_AvgPool3DGradOp : TF_Op<"AvgPool3DGrad", [NoSideEffect]> { + let summary = "Computes gradients of average pooling function."; + + let arguments = (ins + I32Tensor:$orig_input_shape, + TF_FpTensor:$grad, + + Confined]>:$ksize, + Confined]>:$strides, + TF_AnyStrAttrOf<["SAME", "VALID"]>:$padding, + DefaultValuedAttr, "NDHWC">:$data_format + ); + + let results = (outs + TF_FpTensor:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<1>; +} + def TF_AvgPoolGradOp : TF_Op<"AvgPoolGrad", [NoSideEffect]> { let summary = "Computes gradients of the average pooling function."; - let description = [{ - }]; - let arguments = (ins I32Tensor:$orig_input_shape, TF_FpTensor:$grad, @@ -717,7 +798,6 @@ It is computed as: TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_BatchMatMulV2Op : TF_Op<"BatchMatMulV2", [NoSideEffect]> { @@ -766,7 +846,6 @@ about broadcasting return Verify(*this); }]; -// let hasCanonicalizer = 1; } def TF_BatchNormWithGlobalNormalizationOp : TF_Op<"BatchNormWithGlobalNormalization", [NoSideEffect]> { @@ -794,22 +873,24 @@ This op is deprecated. Prefer `tf.nn.batch_normalization`. TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } -def TF_BatchToSpaceNDOp : TF_Op<"BatchToSpaceND", [NoSideEffect]> { - let summary = "BatchToSpace for N-D tensors of type T."; +def TF_BatchToSpaceOp : TF_Op<"BatchToSpace", [NoSideEffect]> { + let summary = "BatchToSpace for 4-D tensors of type T."; let description = [{ -This operation reshapes the "batch" dimension 0 into `M + 1` dimensions of shape -`block_shape + [batch]`, interleaves these blocks back into the grid defined by -the spatial dimensions `[1, ..., M]`, to obtain a result with the same rank as -the input. The spatial dimensions of this intermediate result are then -optionally cropped according to `crops` to produce the output. This is the -reverse of SpaceToBatch. See below for a precise description. +This is a legacy version of the more general BatchToSpaceND. + +Rearranges (permutes) data from batch into blocks of spatial data, followed by +cropping. This is the reverse transformation of SpaceToBatch. More specifically, +this op outputs a copy of the input tensor where values from the `batch` +dimension are moved in spatial blocks to the `height` and `width` dimensions, +followed by cropping along the `height` and `width` dimensions. }]; let arguments = (ins TF_Tensor:$input, - TF_I32OrI64Tensor:$block_shape, - TF_I32OrI64Tensor:$crops + TF_I32OrI64Tensor:$crops, + + Confined]>:$block_size ); let results = (outs @@ -817,50 +898,39 @@ reverse of SpaceToBatch. See below for a precise description. ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; - TF_DerivedOperandTypeAttr Tcrops = TF_DerivedOperandTypeAttr<2>; - TF_DerivedOperandTypeAttr Tblock_shape = TF_DerivedOperandTypeAttr<1>; -} - -def TF_BesselI0eOp : TF_Op<"BesselI0e", [NoSideEffect, SameOperandsAndResultType]> { - let summary = "Computes the Bessel i0e function of `x` element-wise."; - - let description = [{ -Exponentially scaled modified Bessel function of order 0 defined as -`bessel_i0e(x) = exp(-abs(x)) bessel_i0(x)`. + TF_DerivedOperandTypeAttr Tidx = TF_DerivedOperandTypeAttr<1>; -This function is faster and numerically stabler than `bessel_i0(x)`. + let verifier = [{ + return Verify(*this); }]; - let arguments = (ins - TF_FpTensor:$x - ); - - let results = (outs - TF_FpTensor:$y - ); - - TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } -def TF_BesselI1eOp : TF_Op<"BesselI1e", [NoSideEffect, SameOperandsAndResultType]> { - let summary = "Computes the Bessel i1e function of `x` element-wise."; +def TF_BatchToSpaceNDOp : TF_Op<"BatchToSpaceND", [NoSideEffect]> { + let summary = "BatchToSpace for N-D tensors of type T."; let description = [{ -Exponentially scaled modified Bessel function of order 0 defined as -`bessel_i1e(x) = exp(-abs(x)) bessel_i1(x)`. - -This function is faster and numerically stabler than `bessel_i1(x)`. +This operation reshapes the "batch" dimension 0 into `M + 1` dimensions of shape +`block_shape + [batch]`, interleaves these blocks back into the grid defined by +the spatial dimensions `[1, ..., M]`, to obtain a result with the same rank as +the input. The spatial dimensions of this intermediate result are then +optionally cropped according to `crops` to produce the output. This is the +reverse of SpaceToBatch. See below for a precise description. }]; let arguments = (ins - TF_FpTensor:$x + TF_Tensor:$input, + TF_I32OrI64Tensor:$block_shape, + TF_I32OrI64Tensor:$crops ); let results = (outs - TF_FpTensor:$y + TF_Tensor:$output ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; + TF_DerivedOperandTypeAttr Tcrops = TF_DerivedOperandTypeAttr<2>; + TF_DerivedOperandTypeAttr Tblock_shape = TF_DerivedOperandTypeAttr<1>; } def TF_BiasAddOp : TF_Op<"BiasAdd", [NoSideEffect]> { @@ -917,6 +987,29 @@ the feature dimension is the third-to-last. }]; } +def TF_BiasAddV1Op : TF_Op<"BiasAddV1", [NoSideEffect]> { + let summary = "Adds `bias` to `value`."; + + let description = [{ +This is a deprecated version of BiasAdd and will be soon removed. + +This is a special case of `tf.add` where `bias` is restricted to be 1-D. +Broadcasting is supported, so `value` may have any number of dimensions. + }]; + + let arguments = (ins + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$value, + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$bias + ); + + let results = (outs + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; + +} + def TF_BitcastOp : TF_Op<"Bitcast", [NoSideEffect]> { let summary = [{ Bitcasts a tensor from one type to another without copying data. @@ -986,7 +1079,6 @@ endian orderings will give different results. TF_DerivedResultTypeAttr type = TF_DerivedResultTypeAttr<0>; TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_BitwiseAndOp : TF_Op<"BitwiseAnd", [Commutative, NoSideEffect, ResultsBroadcastableShape]>, @@ -1195,6 +1287,35 @@ subsequent operation and then be optimized away, however.) }]; } +def TF_BucketizeOp : TF_Op<"Bucketize", [NoSideEffect, SameOperandsAndResultShape]> { + let summary = "Bucketizes 'input' based on 'boundaries'."; + + let description = [{ +For example, if the inputs are + boundaries = [0, 10, 100] + input = [[-5, 10000] + [150, 10] + [5, 100]] + +then the output will be + output = [[0, 3] + [3, 2] + [1, 3]] + }]; + + let arguments = (ins + TensorOf<[F32, F64, I32, I64]>:$input, + + F32ArrayAttr:$boundaries + ); + + let results = (outs + I32Tensor:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + def TF_CaseOp : TF_Op<"Case", []> { let summary = [{ An n-way switch statement which calls a single branch function. @@ -1233,14 +1354,12 @@ An n-way switch statement, implementing the following: TF_DerivedOperandTypeListAttr Tin = TF_DerivedOperandTypeListAttr<1>; TF_DerivedResultTypeListAttr Tout = TF_DerivedResultTypeListAttr<0>; + } def TF_CastOp : TF_Op<"Cast", [NoSideEffect, SameOperandsAndResultShape]> { let summary = "Cast x of type SrcT to y of DstT."; - let description = [{ - }]; - let arguments = (ins TF_Tensor:$x, @@ -1254,15 +1373,11 @@ def TF_CastOp : TF_Op<"Cast", [NoSideEffect, SameOperandsAndResultShape]> { TF_DerivedOperandTypeAttr SrcT = TF_DerivedOperandTypeAttr<0>; TF_DerivedResultTypeAttr DstT = TF_DerivedResultTypeAttr<0>; -// let hasFolder = 1; } def TF_CeilOp : TF_Op<"Ceil", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Returns element-wise smallest integer not less than x."; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$x ); @@ -1321,15 +1436,13 @@ greater than `clip_value_max` are set to `clip_value_max`. def TF_CollectiveBcastRecvOp : TF_Op<"CollectiveBcastRecv", []> { let summary = "Receives a tensor value broadcast from another device."; - let description = [{ - }]; - let arguments = (ins I64Attr:$group_size, I64Attr:$group_key, I64Attr:$instance_key, TF_ShapeAttr:$shape, - DefaultValuedAttr:$communication_hint + DefaultValuedAttr:$communication_hint, + DefaultValuedAttr:$timeout_seconds ); let results = (outs @@ -1342,9 +1455,6 @@ def TF_CollectiveBcastRecvOp : TF_Op<"CollectiveBcastRecv", []> { def TF_CollectiveBcastSendOp : TF_Op<"CollectiveBcastSend", []> { let summary = "Broadcasts a tensor value to one or more other devices."; - let description = [{ - }]; - let arguments = (ins TensorOf<[F16, F32, F64, I1, I32, I64]>:$input, @@ -1352,7 +1462,8 @@ def TF_CollectiveBcastSendOp : TF_Op<"CollectiveBcastSend", []> { I64Attr:$group_key, I64Attr:$instance_key, TF_ShapeAttr:$shape, - DefaultValuedAttr:$communication_hint + DefaultValuedAttr:$communication_hint, + DefaultValuedAttr:$timeout_seconds ); let results = (outs @@ -1367,9 +1478,6 @@ def TF_CollectiveGatherOp : TF_Op<"CollectiveGather", []> { Mutually accumulates multiple tensors of identical type and shape. }]; - let description = [{ - }]; - let arguments = (ins TensorOf<[F16, F32, F64, I32, I64]>:$input, @@ -1377,7 +1485,8 @@ Mutually accumulates multiple tensors of identical type and shape. I64Attr:$group_key, I64Attr:$instance_key, TF_ShapeAttr:$shape, - DefaultValuedAttr:$communication_hint + DefaultValuedAttr:$communication_hint, + DefaultValuedAttr:$timeout_seconds ); let results = (outs @@ -1387,37 +1496,11 @@ Mutually accumulates multiple tensors of identical type and shape. TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } -def TF_CollectivePermuteOp : TF_Op<"CollectivePermute", [NoSideEffect, SameOperandsAndResultShape]> { - let summary = "An Op to permute tensors across replicated TPU instances."; - - let description = [{ -Each instance supplies its own input. - -For example, suppose there are 4 TPU instances: `[A, B, C, D]`. Passing -source_target_pairs=`[[0,1],[1,2],[2,3],[3,0]]` gets the outputs: -`[D, A, B, C]`. - }]; - - let arguments = (ins - TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$input, - I32Tensor:$source_target_pairs - ); - - let results = (outs - TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$output - ); - - TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -} - def TF_CollectiveReduceOp : TF_Op<"CollectiveReduce", [SameOperandsAndResultType]> { let summary = [{ Mutually reduces multiple tensors of identical type and shape. }]; - let description = [{ - }]; - let arguments = (ins TensorOf<[F16, F32, F64, I32, I64]>:$input, @@ -1428,7 +1511,8 @@ Mutually reduces multiple tensors of identical type and shape. TF_AnyStrAttrOf<["Id", "Div"]>:$final_op, I64ArrayAttr:$subdiv_offsets, DefaultValuedAttr:$wait_for, - DefaultValuedAttr:$communication_hint + DefaultValuedAttr:$communication_hint, + DefaultValuedAttr:$timeout_seconds ); let results = (outs @@ -1496,9 +1580,6 @@ value is computed as \\( \sqrt{a^2 + b^2}\\). def TF_ConcatOp : TF_Op<"Concat", [NoSideEffect]> { let summary = "Concatenates tensors along one dimension."; - let description = [{ - }]; - let arguments = (ins I32Tensor:$concat_dim, Variadic:$values @@ -1514,6 +1595,7 @@ def TF_ConcatOp : TF_Op<"Concat", [NoSideEffect]> { let verifier = [{ return Verify(*this); }]; + } def TF_ConcatOffsetOp : TF_Op<"ConcatOffset", [NoSideEffect]> { @@ -1547,15 +1629,11 @@ This is typically used by gradient computations for a concat operation. return Verify(*this); }]; -// let hasFolder = 1; } def TF_ConcatV2Op : TF_Op<"ConcatV2", [NoSideEffect]> { let summary = "Concatenates tensors along one dimension."; - let description = [{ - }]; - let arguments = (ins Variadic:$values, TF_I32OrI64Tensor:$axis @@ -1603,7 +1681,6 @@ tf.conj(input) ==> [-2.25 - 4.75j, 3.25 - 5.75j] TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_ConjugateTransposeOp : TF_Op<"ConjugateTranspose", [NoSideEffect]> { @@ -1685,8 +1762,6 @@ horizontal and vertices strides, `strides = [1, stride, stride, 1]`. // TF_LayoutSensitiveInterface: SmallVector GetLayoutDependentArgs() { return {0}; } SmallVector GetLayoutDependentResults() { return {0}; } -// StringRef GetOptimalLayout(const RuntimeDevices& devices); -// LogicalResult UpdateDataFormat(StringRef data_format); }]; } @@ -1695,9 +1770,6 @@ def TF_Conv2DBackpropFilterOp : TF_Op<"Conv2DBackpropFilter", [NoSideEffect, TF_ Computes the gradients of convolution with respect to the filter. }]; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$input, I32Tensor:$filter_sizes, @@ -1721,8 +1793,6 @@ Computes the gradients of convolution with respect to the filter. // TF_LayoutSensitiveInterface: SmallVector GetLayoutDependentArgs() { return {0, 2}; } SmallVector GetLayoutDependentResults() { return {}; } -// StringRef GetOptimalLayout(const RuntimeDevices& devices); -// LogicalResult UpdateDataFormat(StringRef data_format); }]; } @@ -1731,9 +1801,6 @@ def TF_Conv2DBackpropInputOp : TF_Op<"Conv2DBackpropInput", [NoSideEffect, TF_La Computes the gradients of convolution with respect to the input. }]; - let description = [{ - }]; - let arguments = (ins I32Tensor:$input_sizes, TensorOf<[BF16, F16, F32, F64, I32]>:$filter, @@ -1761,8 +1828,6 @@ Computes the gradients of convolution with respect to the input. // TF_LayoutSensitiveInterface: SmallVector GetLayoutDependentArgs() { return {2}; } SmallVector GetLayoutDependentResults() { return {0}; } -// StringRef GetOptimalLayout(const RuntimeDevices& devices); -// LogicalResult UpdateDataFormat(StringRef data_format); }]; } @@ -1805,9 +1870,6 @@ def TF_Conv3DBackpropFilterV2Op : TF_Op<"Conv3DBackpropFilterV2", [NoSideEffect] Computes the gradients of 3-D convolution with respect to the filter. }]; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$input, I32Tensor:$filter_sizes, @@ -1831,9 +1893,6 @@ def TF_Conv3DBackpropInputV2Op : TF_Op<"Conv3DBackpropInputV2", [NoSideEffect]> Computes the gradients of 3-D convolution with respect to the input. }]; - let description = [{ - }]; - let arguments = (ins TF_I32OrI64Tensor:$input_sizes, TF_FpTensor:$filter, @@ -2315,6 +2374,25 @@ horizontal and vertices strides, `strides = [1, stride, stride, 1]`. TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } +def TF_DeviceIndexOp : TF_Op<"DeviceIndex", [NoSideEffect]> { + let summary = "Return the index of device the op runs."; + + let description = [{ +Given a list of device names, this operation returns the index of the device +this op runs. The length of the list is returned in two cases: +(1) Device does not exist in the given device list. +(2) It is in XLA compilation. + }]; + + let arguments = (ins + StrArrayAttr:$device_names + ); + + let results = (outs + I32Tensor:$index + ); +} + def TF_DiagPartOp : TF_Op<"DiagPart", [NoSideEffect]> { let summary = "Returns the diagonal part of the tensor."; @@ -2390,9 +2468,7 @@ def TF_DivOp : TF_Op<"Div", [NoSideEffect, ResultsBroadcastableShape]>, TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; -// let hasFolder = 1; } def TF_DivNoNanOp : TF_Op<"DivNoNan", [NoSideEffect, ResultsBroadcastableShape]>, @@ -2630,9 +2706,6 @@ def TF_EluGradOp : TF_Op<"EluGrad", [NoSideEffect, SameOperandsAndResultType]> { Computes gradients for the exponential linear (Elu) operation. }]; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$gradients, TF_FpTensor:$outputs @@ -2652,9 +2725,6 @@ Creates a tensor with the given shape. This operation creates a tensor of `shape` and `dtype`. }]; - let description = [{ - }]; - let arguments = (ins I32Tensor:$shape, @@ -2667,7 +2737,6 @@ This operation creates a tensor of `shape` and `dtype`. TF_DerivedResultTypeAttr dtype = TF_DerivedResultTypeAttr<0>; -// let hasFolder = 1; } def TF_EnqueueTPUEmbeddingRaggedTensorBatchOp : TF_Op<"EnqueueTPUEmbeddingRaggedTensorBatch", [SameVariadicOperandSize]> { @@ -2740,6 +2809,27 @@ the corresponding feature. TF_DerivedOperandSizeAttr N = TF_DerivedOperandSizeAttr<0>; } +def TF_EnsureShapeOp : TF_Op<"EnsureShape", [NoSideEffect]> { + let summary = "Ensures that the tensor's shape matches the expected shape."; + + let description = [{ +Raises an error if the input tensor's shape does not match the specified shape. +Returns the input tensor otherwise. + }]; + + let arguments = (ins + TF_Tensor:$input, + + TF_ShapeAttr:$shape + ); + + let results = (outs + TF_Tensor:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + def TF_EqualOp : TF_Op<"Equal", [Commutative, NoSideEffect]> { let summary = "Returns the truth value of (x == y) element-wise."; @@ -2784,9 +2874,6 @@ tf.math.equal(x, y) ==> array([True, True]) def TF_ErfOp : TF_Op<"Erf", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Computes the Gauss error function of `x` element-wise."; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$x ); @@ -2803,9 +2890,6 @@ def TF_ErfcOp : TF_Op<"Erfc", [NoSideEffect, SameOperandsAndResultType]> { Computes the complementary error function of `x` element-wise. }]; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$x ); @@ -2820,9 +2904,6 @@ Computes the complementary error function of `x` element-wise. def TF_ErfinvOp : TF_Op<"Erfinv", [NoSideEffect]> { let summary = ""; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$x ); @@ -2963,25 +3044,105 @@ i.e. `exp(x) - 1` or `e^(x) - 1`, where `x` is the input tensor. TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } +def TF_FFTOp : TF_Op<"FFT", [NoSideEffect]> { + let summary = "Fast Fourier transform."; + + let description = [{ +Computes the 1-dimensional discrete Fourier transform over the inner-most +dimension of `input`. + }]; + + let arguments = (ins + TensorOf<[TF_Complex128, TF_Complex64]>:$input + ); + + let results = (outs + TensorOf<[TF_Complex128, TF_Complex64]>:$output + ); + + TF_DerivedOperandTypeAttr Tcomplex = TF_DerivedOperandTypeAttr<0>; +} + +def TF_FFT2DOp : TF_Op<"FFT2D", [NoSideEffect]> { + let summary = "2D fast Fourier transform."; + + let description = [{ +Computes the 2-dimensional discrete Fourier transform over the inner-most +2 dimensions of `input`. + }]; + + let arguments = (ins + TensorOf<[TF_Complex128, TF_Complex64]>:$input + ); + + let results = (outs + TensorOf<[TF_Complex128, TF_Complex64]>:$output + ); + + TF_DerivedOperandTypeAttr Tcomplex = TF_DerivedOperandTypeAttr<0>; +} + +def TF_FFT3DOp : TF_Op<"FFT3D", [NoSideEffect]> { + let summary = "3D fast Fourier transform."; + + let description = [{ +Computes the 3-dimensional discrete Fourier transform over the inner-most 3 +dimensions of `input`. + }]; + + let arguments = (ins + TensorOf<[TF_Complex128, TF_Complex64]>:$input + ); + + let results = (outs + TensorOf<[TF_Complex128, TF_Complex64]>:$output + ); + + TF_DerivedOperandTypeAttr Tcomplex = TF_DerivedOperandTypeAttr<0>; +} + +def TF_FakeParamOp : TF_Op<"FakeParam", [NoSideEffect]> { + let summary = [{ + This op is used as a placeholder in If branch functions. It doesn't provide a + valid output when run, so must either be removed (e.g. replaced with a + function input) or guaranteed not to be used (e.g. if mirroring an + intermediate output needed for the gradient computation of the other branch). + }]; + + let arguments = (ins + TF_ShapeAttr:$shape + ); + + let results = (outs + TF_Tensor:$output + ); + + TF_DerivedResultTypeAttr dtype = TF_DerivedResultTypeAttr<0>; +} + def TF_FakeQuantWithMinMaxArgsOp : TF_Op<"FakeQuantWithMinMaxArgs", [NoSideEffect, SameOperandsAndResultType]> { let summary = [{ Fake-quantize the 'inputs' tensor, type float to 'outputs' tensor of same type. }]; let description = [{ -Attributes `[min; max]` define the clamping range for the `inputs` data. -`inputs` values are quantized into the quantization range (`[0; 2^num_bits - 1]` -when `narrow_range` is false and `[1; 2^num_bits - 1]` when it is true) and -then de-quantized and output as floats in `[min; max]` interval. -`num_bits` is the bitwidth of the quantization; between 2 and 16, inclusive. +Attributes + +* `[min; max]` define the clamping range for the `inputs` data. +* `inputs` values are quantized into the quantization range ( +`[0; 2^num_bits - 1]` when `narrow_range` is false and `[1; 2^num_bits - 1]` +when it is true) and then de-quantized and output as floats in `[min; max]` +interval. +* `num_bits` is the bitwidth of the quantization; between 2 and 16, inclusive. Before quantization, `min` and `max` values are adjusted with the following logic. It is suggested to have `min <= 0 <= max`. If `0` is not in the range of values, the behavior can be unexpected: -If `0 < min < max`: `min_adj = 0` and `max_adj = max - min`. -If `min < max < 0`: `min_adj = min - max` and `max_adj = 0`. -If `min <= 0 <= max`: `scale = (max - min) / (2^num_bits - 1) `, + +* If `0 < min < max`: `min_adj = 0` and `max_adj = max - min`. +* If `min < max < 0`: `min_adj = min - max` and `max_adj = 0`. +* If `min <= 0 <= max`: `scale = (max - min) / (2^num_bits - 1) `, `min_adj = scale * round(min / scale)` and `max_adj = max + min_adj - min`. Quantization is called fake since the output is still in floating point. @@ -3007,25 +3168,30 @@ Quantization is called fake since the output is still in floating point. def TF_FakeQuantWithMinMaxVarsOp : TF_Op<"FakeQuantWithMinMaxVars", [NoSideEffect]> { let summary = [{ -Fake-quantize the 'inputs' tensor of type float via global float scalars `min` +Fake-quantize the 'inputs' tensor of type float via global float scalars }]; let description = [{ -and `max` to 'outputs' tensor of same shape as `inputs`. +Fake-quantize the `inputs` tensor of type float via global float scalars +`min` and `max` to `outputs` tensor of same shape as `inputs`. + +Attributes -`[min; max]` define the clamping range for the `inputs` data. -`inputs` values are quantized into the quantization range (`[0; 2^num_bits - 1]` -when `narrow_range` is false and `[1; 2^num_bits - 1]` when it is true) and -then de-quantized and output as floats in `[min; max]` interval. -`num_bits` is the bitwidth of the quantization; between 2 and 16, inclusive. +* `[min; max]` define the clamping range for the `inputs` data. +* `inputs` values are quantized into the quantization range ( +`[0; 2^num_bits - 1]` when `narrow_range` is false and `[1; 2^num_bits - 1]` +when it is true) and then de-quantized and output as floats in `[min; max]` +interval. +* `num_bits` is the bitwidth of the quantization; between 2 and 16, inclusive. Before quantization, `min` and `max` values are adjusted with the following logic. It is suggested to have `min <= 0 <= max`. If `0` is not in the range of values, the behavior can be unexpected: -If `0 < min < max`: `min_adj = 0` and `max_adj = max - min`. -If `min < max < 0`: `min_adj = min - max` and `max_adj = 0`. -If `min <= 0 <= max`: `scale = (max - min) / (2^num_bits - 1) `, + +* If `0 < min < max`: `min_adj = 0` and `max_adj = max - min`. +* If `min < max < 0`: `min_adj = min - max` and `max_adj = 0`. +* If `min <= 0 <= max`: `scale = (max - min) / (2^num_bits - 1) `, `min_adj = scale * round(min / scale)` and `max_adj = max + min_adj - min`. This operation has a gradient and thus allows for training `min` and `max` @@ -3052,26 +3218,31 @@ values. def TF_FakeQuantWithMinMaxVarsPerChannelOp : TF_Op<"FakeQuantWithMinMaxVarsPerChannel", [NoSideEffect]> { let summary = [{ -Fake-quantize the 'inputs' tensor of type float and one of the shapes: `[d]`, +Fake-quantize the 'inputs' tensor of type float via per-channel floats }]; let description = [{ -`[b, d]` `[b, h, w, d]` via per-channel floats `min` and `max` of shape `[d]` -to 'outputs' tensor of same shape as `inputs`. +Fake-quantize the `inputs` tensor of type float per-channel and one of the +shapes: `[d]`, `[b, d]` `[b, h, w, d]` via per-channel floats `min` and `max` +of shape `[d]` to `outputs` tensor of same shape as `inputs`. + +Attributes -`[min; max]` define the clamping range for the `inputs` data. -`inputs` values are quantized into the quantization range (`[0; 2^num_bits - 1]` -when `narrow_range` is false and `[1; 2^num_bits - 1]` when it is true) and -then de-quantized and output as floats in `[min; max]` interval. -`num_bits` is the bitwidth of the quantization; between 2 and 16, inclusive. +* `[min; max]` define the clamping range for the `inputs` data. +* `inputs` values are quantized into the quantization range ( +`[0; 2^num_bits - 1]` when `narrow_range` is false and `[1; 2^num_bits - 1]` +when it is true) and then de-quantized and output as floats in `[min; max]` +interval. +* `num_bits` is the bitwidth of the quantization; between 2 and 16, inclusive. Before quantization, `min` and `max` values are adjusted with the following logic. It is suggested to have `min <= 0 <= max`. If `0` is not in the range of values, the behavior can be unexpected: -If `0 < min < max`: `min_adj = 0` and `max_adj = max - min`. -If `min < max < 0`: `min_adj = min - max` and `max_adj = 0`. -If `min <= 0 <= max`: `scale = (max - min) / (2^num_bits - 1) `, + +* If `0 < min < max`: `min_adj = 0` and `max_adj = max - min`. +* If `min < max < 0`: `min_adj = min - max` and `max_adj = 0`. +* If `min <= 0 <= max`: `scale = (max - min) / (2^num_bits - 1) `, `min_adj = scale * round(min / scale)` and `max_adj = max + min_adj - min`. This operation has a gradient and thus allows for training `min` and `max` @@ -3137,7 +3308,6 @@ fill([2, 3], 9) ==> [[9, 9, 9] return Verify(*this); }]; -// let hasFolder = 1; let builders = [OpBuilder< "OpBuilder &builder, OperationState &result, Value dims, Value value" @@ -3147,9 +3317,6 @@ fill([2, 3], 9) ==> [[9, 9, 9] def TF_FloorOp : TF_Op<"Floor", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Returns element-wise largest integer not greater than x."; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$x ); @@ -3343,8 +3510,6 @@ The size of 1D Tensors matches the dimension C of the 4D Tensors. // TF_LayoutSensitiveInterface: SmallVector GetLayoutDependentArgs() { return {0, 1}; } SmallVector GetLayoutDependentResults() { return {0}; } -// StringRef GetOptimalLayout(const RuntimeDevices& devices); -// LogicalResult UpdateDataFormat(StringRef data_format); }]; } @@ -3385,11 +3550,8 @@ The size of 1D Tensors matches the dimension C of the 4D Tensors. // TF_FoldOperandsTransposeInterface: SmallVector GetLayoutDependentArgs() { return {0}; } SmallVector GetLayoutDependentResults() { return {0}; } -// LogicalResult FoldOperandsPermutation(ArrayRef permutation); // TF_LayoutSensitiveInterface: -// StringRef GetOptimalLayout(const RuntimeDevices& devices); -// LogicalResult UpdateDataFormat(StringRef data_format); }]; } @@ -3686,6 +3848,28 @@ tf.math.greater_equal(x, y) ==> [True, False, True, True] TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } +def TF_HSVToRGBOp : TF_Op<"HSVToRGB", [NoSideEffect]> { + let summary = "Convert one or more images from HSV to RGB."; + + let description = [{ +Outputs a tensor of the same shape as the `images` tensor, containing the RGB +value of the pixels. The output is only well defined if the value in `images` +are in `[0,1]`. + +See `rgb_to_hsv` for a description of the HSV encoding. + }]; + + let arguments = (ins + TF_FpTensor:$images + ); + + let results = (outs + TF_FpTensor:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + def TF_HashTableV2Op : TF_Op<"HashTableV2", []> { let summary = "Creates a non-initialized hash table."; @@ -3704,8 +3888,163 @@ table will be immutable. ); let results = (outs - TF_ResourceTensor:$table_handle + TF_ResourceTensor:$table_handle + ); +} + +def TF_IFFTOp : TF_Op<"IFFT", [NoSideEffect]> { + let summary = "Inverse fast Fourier transform."; + + let description = [{ +Computes the inverse 1-dimensional discrete Fourier transform over the +inner-most dimension of `input`. + }]; + + let arguments = (ins + TensorOf<[TF_Complex128, TF_Complex64]>:$input + ); + + let results = (outs + TensorOf<[TF_Complex128, TF_Complex64]>:$output + ); + + TF_DerivedOperandTypeAttr Tcomplex = TF_DerivedOperandTypeAttr<0>; +} + +def TF_IFFT2DOp : TF_Op<"IFFT2D", [NoSideEffect]> { + let summary = "Inverse 2D fast Fourier transform."; + + let description = [{ +Computes the inverse 2-dimensional discrete Fourier transform over the +inner-most 2 dimensions of `input`. + }]; + + let arguments = (ins + TensorOf<[TF_Complex128, TF_Complex64]>:$input + ); + + let results = (outs + TensorOf<[TF_Complex128, TF_Complex64]>:$output + ); + + TF_DerivedOperandTypeAttr Tcomplex = TF_DerivedOperandTypeAttr<0>; +} + +def TF_IFFT3DOp : TF_Op<"IFFT3D", [NoSideEffect]> { + let summary = "Inverse 3D fast Fourier transform."; + + let description = [{ +Computes the inverse 3-dimensional discrete Fourier transform over the +inner-most 3 dimensions of `input`. + }]; + + let arguments = (ins + TensorOf<[TF_Complex128, TF_Complex64]>:$input + ); + + let results = (outs + TensorOf<[TF_Complex128, TF_Complex64]>:$output + ); + + TF_DerivedOperandTypeAttr Tcomplex = TF_DerivedOperandTypeAttr<0>; +} + +def TF_IRFFTOp : TF_Op<"IRFFT", [NoSideEffect]> { + let summary = "Inverse real-valued fast Fourier transform."; + + let description = [{ +Computes the inverse 1-dimensional discrete Fourier transform of a real-valued +signal over the inner-most dimension of `input`. + +The inner-most dimension of `input` is assumed to be the result of `RFFT`: the +`fft_length / 2 + 1` unique components of the DFT of a real-valued signal. If +`fft_length` is not provided, it is computed from the size of the inner-most +dimension of `input` (`fft_length = 2 * (inner - 1)`). If the FFT length used to +compute `input` is odd, it should be provided since it cannot be inferred +properly. + +Along the axis `IRFFT` is computed on, if `fft_length / 2 + 1` is smaller +than the corresponding dimension of `input`, the dimension is cropped. If it is +larger, the dimension is padded with zeros. + }]; + + let arguments = (ins + TensorOf<[TF_Complex128, TF_Complex64]>:$input, + I32Tensor:$fft_length + ); + + let results = (outs + TF_F32OrF64Tensor:$output + ); + + TF_DerivedResultTypeAttr Treal = TF_DerivedResultTypeAttr<0>; + TF_DerivedOperandTypeAttr Tcomplex = TF_DerivedOperandTypeAttr<0>; +} + +def TF_IRFFT2DOp : TF_Op<"IRFFT2D", [NoSideEffect]> { + let summary = "Inverse 2D real-valued fast Fourier transform."; + + let description = [{ +Computes the inverse 2-dimensional discrete Fourier transform of a real-valued +signal over the inner-most 2 dimensions of `input`. + +The inner-most 2 dimensions of `input` are assumed to be the result of `RFFT2D`: +The inner-most dimension contains the `fft_length / 2 + 1` unique components of +the DFT of a real-valued signal. If `fft_length` is not provided, it is computed +from the size of the inner-most 2 dimensions of `input`. If the FFT length used +to compute `input` is odd, it should be provided since it cannot be inferred +properly. + +Along each axis `IRFFT2D` is computed on, if `fft_length` (or +`fft_length / 2 + 1` for the inner-most dimension) is smaller than the +corresponding dimension of `input`, the dimension is cropped. If it is larger, +the dimension is padded with zeros. + }]; + + let arguments = (ins + TensorOf<[TF_Complex128, TF_Complex64]>:$input, + I32Tensor:$fft_length + ); + + let results = (outs + TF_F32OrF64Tensor:$output + ); + + TF_DerivedResultTypeAttr Treal = TF_DerivedResultTypeAttr<0>; + TF_DerivedOperandTypeAttr Tcomplex = TF_DerivedOperandTypeAttr<0>; +} + +def TF_IRFFT3DOp : TF_Op<"IRFFT3D", [NoSideEffect]> { + let summary = "Inverse 3D real-valued fast Fourier transform."; + + let description = [{ +Computes the inverse 3-dimensional discrete Fourier transform of a real-valued +signal over the inner-most 3 dimensions of `input`. + +The inner-most 3 dimensions of `input` are assumed to be the result of `RFFT3D`: +The inner-most dimension contains the `fft_length / 2 + 1` unique components of +the DFT of a real-valued signal. If `fft_length` is not provided, it is computed +from the size of the inner-most 3 dimensions of `input`. If the FFT length used +to compute `input` is odd, it should be provided since it cannot be inferred +properly. + +Along each axis `IRFFT3D` is computed on, if `fft_length` (or +`fft_length / 2 + 1` for the inner-most dimension) is smaller than the +corresponding dimension of `input`, the dimension is cropped. If it is larger, +the dimension is padded with zeros. + }]; + + let arguments = (ins + TensorOf<[TF_Complex128, TF_Complex64]>:$input, + I32Tensor:$fft_length + ); + + let results = (outs + TF_F32OrF64Tensor:$output ); + + TF_DerivedResultTypeAttr Treal = TF_DerivedResultTypeAttr<0>; + TF_DerivedOperandTypeAttr Tcomplex = TF_DerivedOperandTypeAttr<0>; } def TF_IdentityNOp : TF_Op<"IdentityN", [NoSideEffect]> { @@ -3780,9 +4119,6 @@ def TF_IgammaGradAOp : TF_Op<"IgammaGradA", [NoSideEffect, ResultsBroadcastableS WithBroadcastableBinOpBuilder { let summary = "Computes the gradient of `igamma(a, x)` wrt `a`."; - let description = [{ - }]; - let arguments = (ins TF_F32OrF64Tensor:$a, TF_F32OrF64Tensor:$x @@ -3857,6 +4193,35 @@ tf.imag(input) ==> [4.75, 5.75] TF_DerivedResultTypeAttr Tout = TF_DerivedResultTypeAttr<0>; } +def TF_InitializeTableFromTextFileV2Op : TF_Op<"InitializeTableFromTextFileV2", []> { + let summary = "Initializes a table from a text file."; + + let description = [{ +It inserts one key-value pair into the table for each line of the file. +The key and value is extracted from the whole line content, elements from the +split line based on `delimiter` or the line number (starting from zero). +Where to extract the key and value from a line is specified by `key_index` and +`value_index`. + +- A value of -1 means use the line number(starting from zero), expects `int64`. +- A value of -2 means use the whole line content, expects `string`. +- A value >= 0 means use the index (starting at zero) of the split line based + on `delimiter`. + }]; + + let arguments = (ins + TF_ResourceTensor:$table_handle, + TF_StrTensor:$filename, + + Confined]>:$key_index, + Confined]>:$value_index, + Confined, [IntMinValue<-1>]>:$vocab_size, + DefaultValuedAttr:$delimiter + ); + + let results = (outs); +} + def TF_InvOp : TF_Op<"Inv", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Computes the reciprocal of x element-wise."; @@ -3865,11 +4230,11 @@ I.e., \\(y = 1 / x\\). }]; let arguments = (ins - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$x + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$x ); let results = (outs - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$y + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$y ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; @@ -3932,7 +4297,6 @@ for dtype in dtype_list: TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_InvertPermutationOp : TF_Op<"InvertPermutation", [NoSideEffect]> { @@ -4055,9 +4419,6 @@ tf.math.is_nan(x) ==> [False, True, False, True, False] def TF_IteratorGetNextOp : TF_Op<"IteratorGetNext", []> { let summary = "Gets the next output from the given iterator ."; - let description = [{ - }]; - let arguments = (ins TF_ResourceTensor:$iterator ); @@ -4123,12 +4484,30 @@ convolutional neural networks (NIPS 2012)](http://papers.nips.cc/paper/4824-imag TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } +def TF_LRNGradOp : TF_Op<"LRNGrad", [NoSideEffect]> { + let summary = "Gradients for Local Response Normalization."; + + let arguments = (ins + TensorOf<[BF16, F16, F32]>:$input_grads, + TensorOf<[BF16, F16, F32]>:$input_image, + TensorOf<[BF16, F16, F32]>:$output_image, + + DefaultValuedAttr:$depth_radius, + DefaultValuedAttr:$bias, + DefaultValuedAttr:$alpha, + DefaultValuedAttr:$beta + ); + + let results = (outs + TensorOf<[BF16, F16, F32]>:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + def TF_LeakyReluOp : TF_Op<"LeakyRelu", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Computes rectified linear: `max(features, features * alpha)`."; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$features, @@ -4141,7 +4520,6 @@ def TF_LeakyReluOp : TF_Op<"LeakyRelu", [NoSideEffect, SameOperandsAndResultType TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasFolder = 1; } def TF_LeakyReluGradOp : TF_Op<"LeakyReluGrad", [NoSideEffect, SameOperandsAndResultType]> { @@ -4149,9 +4527,6 @@ def TF_LeakyReluGradOp : TF_Op<"LeakyReluGrad", [NoSideEffect, SameOperandsAndRe Computes rectified linear gradients for a LeakyRelu operation. }]; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$gradients, TF_FpTensor:$features, @@ -4362,7 +4737,6 @@ tf.math.log(x) ==> [-inf, -0.6931472, 0. , 1.609438] TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_Log1pOp : TF_Op<"Log1p", [NoSideEffect, SameOperandsAndResultType]> { @@ -4432,9 +4806,6 @@ def TF_LogicalAndOp : TF_Op<"LogicalAnd", [Commutative, NoSideEffect, ResultsBro def TF_LogicalNotOp : TF_Op<"LogicalNot", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Returns the truth value of `NOT x` element-wise."; - let description = [{ - }]; - let arguments = (ins I1Tensor:$x ); @@ -4443,7 +4814,6 @@ def TF_LogicalNotOp : TF_Op<"LogicalNot", [NoSideEffect, SameOperandsAndResultTy I1Tensor:$y ); -// let hasCanonicalizer = 1; } def TF_LogicalOrOp : TF_Op<"LogicalOr", [Commutative, NoSideEffect, ResultsBroadcastableShape]>, @@ -4515,9 +4885,6 @@ The tensor `values` must be of the type of the table values. def TF_LookupTableSizeV2Op : TF_Op<"LookupTableSizeV2", []> { let summary = "Computes the number of elements in the given table."; - let description = [{ - }]; - let arguments = (ins TF_ResourceTensor:$table_handle ); @@ -5202,9 +5569,6 @@ retained with length 1. def TF_MaxPoolOp : TF_Op<"MaxPool", [NoSideEffect, TF_FoldOperandsTransposeInterface]> { let summary = "Performs max pooling on the input."; - let description = [{ - }]; - let arguments = (ins TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Qint8, TF_Uint16, TF_Uint8]>:$input, @@ -5224,16 +5588,12 @@ def TF_MaxPoolOp : TF_Op<"MaxPool", [NoSideEffect, TF_FoldOperandsTransposeInter // TF_FoldOperandsTransposeInterface: SmallVector GetLayoutDependentArgs() { return {0}; } SmallVector GetLayoutDependentResults() { return {0}; } -// LogicalResult FoldOperandsPermutation(ArrayRef permutation); }]; } def TF_MaxPool3DOp : TF_Op<"MaxPool3D", [NoSideEffect]> { let summary = "Performs 3D max pooling on the input."; - let description = [{ - }]; - let arguments = (ins TensorOf<[BF16, F16, F32]>:$input, @@ -5253,9 +5613,6 @@ def TF_MaxPool3DOp : TF_Op<"MaxPool3D", [NoSideEffect]> { def TF_MaxPool3DGradOp : TF_Op<"MaxPool3DGrad", [NoSideEffect]> { let summary = "Computes gradients of 3D max pooling function."; - let description = [{ - }]; - let arguments = (ins TensorOf<[BF16, F16, F32]>:$orig_input, TensorOf<[BF16, F16, F32]>:$orig_output, @@ -5278,9 +5635,6 @@ def TF_MaxPool3DGradOp : TF_Op<"MaxPool3DGrad", [NoSideEffect]> { def TF_MaxPoolGradOp : TF_Op<"MaxPoolGrad", [NoSideEffect]> { let summary = "Computes gradients of the maxpooling function."; - let description = [{ - }]; - let arguments = (ins TF_IntOrFpTensor:$orig_input, TF_IntOrFpTensor:$orig_output, @@ -5324,6 +5678,32 @@ def TF_MaximumOp : TF_Op<"Maximum", [NoSideEffect, ResultsBroadcastableShape]>, TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } +def TF_MergeV2CheckpointsOp : TF_Op<"MergeV2Checkpoints", []> { + let summary = [{ +V2 format specific: merges the metadata files of sharded checkpoints. The + }]; + + let description = [{ +result is one logical checkpoint, with one physical metadata file and renamed +data files. + +Intended for "grouping" multiple checkpoints in a sharded checkpoint setup. + +If delete_old_dirs is true, attempts to delete recursively the dirname of each +path in the input checkpoint_prefixes. This is useful when those paths are non +user-facing temporary locations. + }]; + + let arguments = (ins + TF_StrTensor:$checkpoint_prefixes, + TF_StrTensor:$destination_prefix, + + DefaultValuedAttr:$delete_old_dirs + ); + + let results = (outs); +} + def TF_MinOp : TF_Op<"Min", [NoSideEffect]> { let summary = [{ Computes the minimum of elements across dimensions of a tensor. @@ -5530,7 +5910,6 @@ def TF_MulOp : TF_Op<"Mul", [Commutative, NoSideEffect, ResultsBroadcastableShap TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasFolder = 1; } def TF_MulNoNanOp : TF_Op<"MulNoNan", [NoSideEffect, ResultsBroadcastableShape]>, @@ -5559,9 +5938,6 @@ Returns x * y element-wise. Returns zero if y is zero, even if x if infinite or def TF_MultinomialOp : TF_Op<"Multinomial", []> { let summary = "Draws samples from a multinomial distribution."; - let description = [{ - }]; - let arguments = (ins TF_IntOrFpTensor:$logits, I32Tensor:$num_samples, @@ -5581,9 +5957,6 @@ def TF_MultinomialOp : TF_Op<"Multinomial", []> { def TF_NdtriOp : TF_Op<"Ndtri", [NoSideEffect]> { let summary = ""; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$x ); @@ -5603,24 +5976,20 @@ I.e., \\(y = -x\\). }]; let arguments = (ins - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$x + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$x ); let results = (outs - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$y + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$y ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_NoOp : TF_Op<"NoOp", [NoSideEffect]> { let summary = "Does nothing. Only useful as a placeholder for control edges."; - let description = [{ - }]; - let arguments = (ins); let results = (outs); @@ -5874,9 +6243,6 @@ output = def TF_OutfeedEnqueueTupleOp : TF_Op<"OutfeedEnqueueTuple", []> { let summary = "Enqueue multiple Tensor values on the computation outfeed."; - let description = [{ - }]; - let arguments = (ins Variadic:$inputs ); @@ -5975,7 +6341,6 @@ pad(t, paddings) ==> [[0, 0, 0, 0, 0, 0] // TF_FoldOperandsTransposeInterface: SmallVector GetLayoutDependentArgs() { return {0}; } SmallVector GetLayoutDependentResults() { return {0}; } -// LogicalResult FoldOperandsPermutation(ArrayRef permutation); }]; } @@ -6049,7 +6414,6 @@ tf.pow(x, y) ==> [[256, 65536], [9, 27]] TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasFolder = 1; } def TF_PreventGradientOp : TF_Op<"PreventGradient", [NoSideEffect, SameOperandsAndResultType]> { @@ -6161,9 +6525,6 @@ q_full, r_full = qr(a, full_matrices=True) def TF_QuantizeAndDequantizeOp : TF_Op<"QuantizeAndDequantize", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Use QuantizeAndDequantizeV2 instead."; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$input, @@ -6314,15 +6675,107 @@ the dimension is padded with zeros. TF_DerivedResultTypeAttr Tcomplex = TF_DerivedResultTypeAttr<0>; } +def TF_RFFT2DOp : TF_Op<"RFFT2D", [NoSideEffect]> { + let summary = "2D real-valued fast Fourier transform."; + + let description = [{ +Computes the 2-dimensional discrete Fourier transform of a real-valued signal +over the inner-most 2 dimensions of `input`. + +Since the DFT of a real signal is Hermitian-symmetric, `RFFT2D` only returns the +`fft_length / 2 + 1` unique components of the FFT for the inner-most dimension +of `output`: the zero-frequency term, followed by the `fft_length / 2` +positive-frequency terms. + +Along each axis `RFFT2D` is computed on, if `fft_length` is smaller than the +corresponding dimension of `input`, the dimension is cropped. If it is larger, +the dimension is padded with zeros. + }]; + + let arguments = (ins + TF_F32OrF64Tensor:$input, + I32Tensor:$fft_length + ); + + let results = (outs + TensorOf<[TF_Complex128, TF_Complex64]>:$output + ); + + TF_DerivedOperandTypeAttr Treal = TF_DerivedOperandTypeAttr<0>; + TF_DerivedResultTypeAttr Tcomplex = TF_DerivedResultTypeAttr<0>; +} + +def TF_RFFT3DOp : TF_Op<"RFFT3D", [NoSideEffect]> { + let summary = "3D real-valued fast Fourier transform."; + + let description = [{ +Computes the 3-dimensional discrete Fourier transform of a real-valued signal +over the inner-most 3 dimensions of `input`. + +Since the DFT of a real signal is Hermitian-symmetric, `RFFT3D` only returns the +`fft_length / 2 + 1` unique components of the FFT for the inner-most dimension +of `output`: the zero-frequency term, followed by the `fft_length / 2` +positive-frequency terms. + +Along each axis `RFFT3D` is computed on, if `fft_length` is smaller than the +corresponding dimension of `input`, the dimension is cropped. If it is larger, +the dimension is padded with zeros. + }]; + + let arguments = (ins + TF_F32OrF64Tensor:$input, + I32Tensor:$fft_length + ); + + let results = (outs + TensorOf<[TF_Complex128, TF_Complex64]>:$output + ); + + TF_DerivedOperandTypeAttr Treal = TF_DerivedOperandTypeAttr<0>; + TF_DerivedResultTypeAttr Tcomplex = TF_DerivedResultTypeAttr<0>; +} + +def TF_RGBToHSVOp : TF_Op<"RGBToHSV", [NoSideEffect]> { + let summary = "Converts one or more images from RGB to HSV."; + + let description = [{ +Outputs a tensor of the same shape as the `images` tensor, containing the HSV +value of the pixels. The output is only well defined if the value in `images` +are in `[0,1]`. + +`output[..., 0]` contains hue, `output[..., 1]` contains saturation, and +`output[..., 2]` contains value. All HSV values are in `[0,1]`. A hue of 0 +corresponds to pure red, hue 1/3 is pure green, and 2/3 is pure blue. + +Usage Example: + +>>> blue_image = tf.stack([ +... tf.zeros([5,5]), +... tf.zeros([5,5]), +... tf.ones([5,5])], +... axis=-1) +>>> blue_hsv_image = tf.image.rgb_to_hsv(blue_image) +>>> blue_hsv_image[0,0].numpy() +array([0.6666667, 1. , 1. ], dtype=float32) + }]; + + let arguments = (ins + TF_FpTensor:$images + ); + + let results = (outs + TF_FpTensor:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + def TF_RandomGammaGradOp : TF_Op<"RandomGammaGrad", [NoSideEffect, ResultsBroadcastableShape]>, WithBroadcastableBinOpBuilder { let summary = [{ Computes the derivative of a Gamma random sample w.r.t. `alpha`. }]; - let description = [{ - }]; - let arguments = (ins TF_F32OrF64Tensor:$alpha, TF_F32OrF64Tensor:$sample @@ -6481,7 +6934,6 @@ of the tensor. Rank is also known as "order", "degree", or "ndims." OpBuilder<"OpBuilder& builder, OperationState& result, Value input"> ]; -// let hasFolder = 1; } def TF_ReadVariableOp : TF_Op<"ReadVariableOp", []> { @@ -6497,7 +6949,7 @@ operation. }]; let arguments = (ins - TF_ResourceTensor:$resource + Arg:$resource ); let results = (outs @@ -6506,7 +6958,6 @@ operation. TF_DerivedResultTypeAttr dtype = TF_DerivedResultTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_RealOp : TF_Op<"Real", [NoSideEffect, SameOperandsAndResultShape]> { @@ -6560,9 +7011,7 @@ If `x` and `y` are reals, this will return the floating-point division. TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; -// let hasFolder = 1; } def TF_ReciprocalOp : TF_Op<"Reciprocal", [NoSideEffect, SameOperandsAndResultType]> { @@ -6573,16 +7022,15 @@ I.e., \\(y = 1 / x\\). }]; let arguments = (ins - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$x + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$x ); let results = (outs - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$y + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$y ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_ReciprocalGradOp : TF_Op<"ReciprocalGrad", [NoSideEffect, SameOperandsAndResultType]> { @@ -6652,9 +7100,6 @@ array([ 0., 0., -0., 3.], dtype=float32) def TF_Relu6Op : TF_Op<"Relu6", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Computes rectified linear 6: `min(max(features, 0), 6)`."; - let description = [{ - }]; - let arguments = (ins TF_IntOrFpTensor:$features ); @@ -6669,9 +7114,6 @@ def TF_Relu6Op : TF_Op<"Relu6", [NoSideEffect, SameOperandsAndResultType]> { def TF_Relu6GradOp : TF_Op<"Relu6Grad", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Computes rectified linear 6 gradients for a Relu6 operation."; - let description = [{ - }]; - let arguments = (ins TF_IntOrFpTensor:$gradients, TF_IntOrFpTensor:$features @@ -6687,9 +7129,6 @@ def TF_Relu6GradOp : TF_Op<"Relu6Grad", [NoSideEffect, SameOperandsAndResultType def TF_ReluGradOp : TF_Op<"ReluGrad", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Computes rectified linear gradients for a Relu operation."; - let description = [{ - }]; - let arguments = (ins TF_IntOrFpTensor:$gradients, TF_IntOrFpTensor:$features @@ -6811,14 +7250,29 @@ Input images can be of different types but output images are always float. TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } +def TF_ResizeBilinearGradOp : TF_Op<"ResizeBilinearGrad", [NoSideEffect]> { + let summary = "Computes the gradient of bilinear interpolation."; + + let arguments = (ins + F32Tensor:$grads, + TF_FpTensor:$original_image, + + DefaultValuedAttr:$align_corners, + DefaultValuedAttr:$half_pixel_centers + ); + + let results = (outs + TF_FpTensor:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<1>; +} + def TF_ResizeNearestNeighborOp : TF_Op<"ResizeNearestNeighbor", [NoSideEffect]> { let summary = [{ Resize `images` to `size` using nearest neighbor interpolation. }]; - let description = [{ - }]; - let arguments = (ins TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Uint16, TF_Uint8]>:$images, I32Tensor:$size, @@ -6889,12 +7343,52 @@ $$\text{variable} := \text{variable} - \text{lr}_t * m_t / (\sqrt{v_t} + \epsilo TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<3>; } -def TF_ResourceApplyGradientDescentOp : TF_Op<"ResourceApplyGradientDescent", []> { - let summary = "Update '*var' by subtracting 'alpha' * 'delta' from it."; +def TF_ResourceApplyCenteredRMSPropOp : TF_Op<"ResourceApplyCenteredRMSProp", []> { + let summary = "Update '*var' according to the centered RMSProp algorithm."; let description = [{ +The centered RMSProp algorithm uses an estimate of the centered second moment +(i.e., the variance) for normalization, as opposed to regular RMSProp, which +uses the (uncentered) second moment. This often helps with training, but is +slightly more expensive in terms of computation and memory. + +Note that in dense implementation of this algorithm, mg, ms, and mom will +update even if the grad is zero, but in this sparse implementation, mg, ms, +and mom will not update in iterations during which the grad is zero. + +mean_square = decay * mean_square + (1-decay) * gradient ** 2 +mean_grad = decay * mean_grad + (1-decay) * gradient + +Delta = learning_rate * gradient / sqrt(mean_square + epsilon - mean_grad ** 2) + +mg <- rho * mg_{t-1} + (1-rho) * grad +ms <- rho * ms_{t-1} + (1-rho) * grad * grad +mom <- momentum * mom_{t-1} + lr * grad / sqrt(ms - mg * mg + epsilon) +var <- var - mom }]; + let arguments = (ins + TF_ResourceTensor:$var, + TF_ResourceTensor:$mg, + TF_ResourceTensor:$ms, + TF_ResourceTensor:$mom, + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$lr, + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$rho, + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$momentum, + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$epsilon, + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$grad, + + DefaultValuedAttr:$use_locking + ); + + let results = (outs); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<4>; +} + +def TF_ResourceApplyGradientDescentOp : TF_Op<"ResourceApplyGradientDescent", []> { + let summary = "Update '*var' by subtracting 'alpha' * 'delta' from it."; + let arguments = (ins TF_ResourceTensor:$var, TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$alpha, @@ -7027,6 +7521,38 @@ This operation computes TF_DerivedOperandTypeAttr dtype = TF_DerivedOperandTypeAttr<2>; } +def TF_RestoreV2Op : TF_Op<"RestoreV2", []> { + let summary = "Restores tensors from a V2 checkpoint."; + + let description = [{ +For backward compatibility with the V1 format, this Op currently allows +restoring from a V1 checkpoint as well: + - This Op first attempts to find the V2 index file pointed to by "prefix", and + if found proceed to read it as a V2 checkpoint; + - Otherwise the V1 read path is invoked. +Relying on this behavior is not recommended, as the ability to fall back to read +V1 might be deprecated and eventually removed. + +By default, restores the named tensors in full. If the caller wishes to restore +specific slices of stored tensors, "shape_and_slices" should be non-empty +strings and correspondingly well-formed. + +Callers must ensure all the named tensors are indeed stored in the checkpoint. + }]; + + let arguments = (ins + TF_StrTensor:$prefix, + TF_StrTensor:$tensor_names, + TF_StrTensor:$shape_and_slices + ); + + let results = (outs + Variadic:$tensors + ); + + TF_DerivedResultTypeListAttr dtypes = TF_DerivedResultTypeListAttr<0>; +} + def TF_ReverseSequenceOp : TF_Op<"ReverseSequence", [NoSideEffect]> { let summary = "Reverses variable length slices."; @@ -7257,11 +7783,11 @@ according to the current system rounding mode use std::cint. }]; let arguments = (ins - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$x + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$x ); let results = (outs - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$y + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$y ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; @@ -7667,7 +8193,6 @@ select(condition, t, e) ==> [[1, 2], TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<1>; -// let hasCanonicalizer = 1; let verifier = [{ return Verify(*this); @@ -7677,9 +8202,6 @@ select(condition, t, e) ==> [[1, 2], def TF_SelectV2Op : TF_Op<"SelectV2", [NoSideEffect, ResultsBroadcastableShape]> { let summary = ""; - let description = [{ - }]; - let arguments = (ins I1Tensor:$condition, TF_Tensor:$t, @@ -7728,9 +8250,6 @@ def TF_SeluGradOp : TF_Op<"SeluGrad", [NoSideEffect, SameOperandsAndResultType]> Computes gradients for the scaled exponential linear (Selu) operation. }]; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$gradients, TF_FpTensor:$outputs @@ -7776,7 +8295,6 @@ shape(t) ==> [2, 2, 3] OpBuilder<"OpBuilder& builder, OperationState& result, Value input, BoolAttr use32Bit"> ]; -// let hasFolder = 1; } def TF_ShapeNOp : TF_Op<"ShapeN", [NoSideEffect]> { @@ -7802,7 +8320,26 @@ This operation returns N 1-D integer tensors representing shape of `input[i]s`. return Verify(*this); }]; -// let hasFolder = 1; +} + +def TF_ShardedFilenameOp : TF_Op<"ShardedFilename", [NoSideEffect]> { + let summary = [{ +Generate a sharded filename. The filename is printf formatted as + }]; + + let description = [{ +%s-%05d-of-%05d, basename, shard, num_shards. + }]; + + let arguments = (ins + TF_StrTensor:$basename, + I32Tensor:$shard, + I32Tensor:$num_shards + ); + + let results = (outs + TF_StrTensor:$filename + ); } def TF_SigmoidOp : TF_Op<"Sigmoid", [NoSideEffect, SameOperandsAndResultType]> { @@ -7981,9 +8518,6 @@ whose values are extracted from 'input' starting at the offsets in def TF_SnapshotOp : TF_Op<"Snapshot", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Returns a copy of the input tensor."; - let description = [{ - }]; - let arguments = (ins TF_Tensor:$input ); @@ -8045,11 +8579,8 @@ Inputs are the logits, not probabilities. }]; } -def TF_SoftplusOp : TF_Op<"Softplus", [NoSideEffect, SameOperandsAndResultType]> { - let summary = "Computes softplus: `log(exp(features) + 1)`."; - - let description = [{ - }]; +def TF_SoftplusOp : TF_Op<"Softplus", [NoSideEffect, SameOperandsAndResultType]> { + let summary = "Computes softplus: `log(exp(features) + 1)`."; let arguments = (ins TF_FpTensor:$features @@ -8065,9 +8596,6 @@ def TF_SoftplusOp : TF_Op<"Softplus", [NoSideEffect, SameOperandsAndResultType]> def TF_SoftplusGradOp : TF_Op<"SoftplusGrad", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Computes softplus gradients for a softplus operation."; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$gradients, TF_FpTensor:$features @@ -8083,9 +8611,6 @@ def TF_SoftplusGradOp : TF_Op<"SoftplusGrad", [NoSideEffect, SameOperandsAndResu def TF_SoftsignOp : TF_Op<"Softsign", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Computes softsign: `features / (abs(features) + 1)`."; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$features ); @@ -8100,9 +8625,6 @@ def TF_SoftsignOp : TF_Op<"Softsign", [NoSideEffect, SameOperandsAndResultType]> def TF_SoftsignGradOp : TF_Op<"SoftsignGrad", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Computes softsign gradients for a softsign operation."; - let description = [{ - }]; - let arguments = (ins TF_FpTensor:$gradients, TF_FpTensor:$features @@ -8115,6 +8637,34 @@ def TF_SoftsignGradOp : TF_Op<"SoftsignGrad", [NoSideEffect, SameOperandsAndResu TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } +def TF_SpaceToBatchOp : TF_Op<"SpaceToBatch", [NoSideEffect]> { + let summary = "SpaceToBatch for 4-D tensors of type T."; + + let description = [{ +This is a legacy version of the more general SpaceToBatchND. + +Zero-pads and then rearranges (permutes) blocks of spatial data into batch. +More specifically, this op outputs a copy of the input tensor where values from +the `height` and `width` dimensions are moved to the `batch` dimension. After +the zero-padding, both `height` and `width` of the input must be divisible by the +block size. + }]; + + let arguments = (ins + TF_Tensor:$input, + TF_I32OrI64Tensor:$paddings, + + Confined]>:$block_size + ); + + let results = (outs + TF_Tensor:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; + TF_DerivedOperandTypeAttr Tpaddings = TF_DerivedOperandTypeAttr<1>; +} + def TF_SpaceToBatchNDOp : TF_Op<"SpaceToBatchND", [NoSideEffect]> { let summary = "SpaceToBatch for N-D tensors of type T."; @@ -8247,6 +8797,128 @@ x = [[[[1, 2, 3, 4], TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } +def TF_SparseFillEmptyRowsOp : TF_Op<"SparseFillEmptyRows", [NoSideEffect]> { + let summary = [{ +Fills empty rows in the input 2-D `SparseTensor` with a default value. + }]; + + let description = [{ +The input `SparseTensor` is represented via the tuple of inputs +(`indices`, `values`, `dense_shape`). The output `SparseTensor` has the +same `dense_shape` but with indices `output_indices` and values +`output_values`. + +This op inserts a single entry for every row that doesn't have any values. +The index is created as `[row, 0, ..., 0]` and the inserted value +is `default_value`. + +For example, suppose `sp_input` has shape `[5, 6]` and non-empty values: + + [0, 1]: a + [0, 3]: b + [2, 0]: c + [3, 1]: d + +Rows 1 and 4 are empty, so the output will be of shape `[5, 6]` with values: + + [0, 1]: a + [0, 3]: b + [1, 0]: default_value + [2, 0]: c + [3, 1]: d + [4, 0]: default_value + +The output `SparseTensor` will be in row-major order and will have the +same shape as the input. + +This op also returns an indicator vector shaped `[dense_shape[0]]` such that + + empty_row_indicator[i] = True iff row i was an empty row. + +And a reverse index map vector shaped `[indices.shape[0]]` that is used during +backpropagation, + + reverse_index_map[j] = out_j s.t. indices[j, :] == output_indices[out_j, :] + }]; + + let arguments = (ins + I64Tensor:$indices, + TF_Tensor:$values, + I64Tensor:$dense_shape, + TF_Tensor:$default_value + ); + + let results = (outs + I64Tensor:$output_indices, + TF_Tensor:$output_values, + I1Tensor:$empty_row_indicator, + I64Tensor:$reverse_index_map + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<1>; +} + +def TF_SparseReshapeOp : TF_Op<"SparseReshape", [NoSideEffect]> { + let summary = [{ +Reshapes a SparseTensor to represent values in a new dense shape. + }]; + + let description = [{ +This operation has the same semantics as reshape on the represented dense +tensor. The `input_indices` are recomputed based on the requested `new_shape`. + +If one component of `new_shape` is the special value -1, the size of that +dimension is computed so that the total dense size remains constant. At +most one component of `new_shape` can be -1. The number of dense elements +implied by `new_shape` must be the same as the number of dense elements +originally implied by `input_shape`. + +Reshaping does not affect the order of values in the SparseTensor. + +If the input tensor has rank `R_in` and `N` non-empty values, and `new_shape` +has length `R_out`, then `input_indices` has shape `[N, R_in]`, +`input_shape` has length `R_in`, `output_indices` has shape `[N, R_out]`, and +`output_shape` has length `R_out`. + }]; + + let arguments = (ins + I64Tensor:$input_indices, + I64Tensor:$input_shape, + I64Tensor:$new_shape + ); + + let results = (outs + I64Tensor:$output_indices, + I64Tensor:$output_shape + ); +} + +def TF_SparseSegmentSqrtNOp : TF_Op<"SparseSegmentSqrtN", [NoSideEffect]> { + let summary = [{ +Computes the sum along sparse segments of a tensor divided by the sqrt of N. + }]; + + let description = [{ +N is the size of the segment being reduced. + +See `tf.sparse.segment_sum` for usage examples. + }]; + + let arguments = (ins + TensorOf<[BF16, F32, F64]>:$data, + TF_I32OrI64Tensor:$indices, + TF_I32OrI64Tensor:$segment_ids + ); + + let results = (outs + TensorOf<[BF16, F32, F64]>:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; + TF_DerivedOperandTypeAttr Tsegmentids = TF_DerivedOperandTypeAttr<2>; + TF_DerivedOperandTypeAttr Tidx = TF_DerivedOperandTypeAttr<1>; +} + def TF_SparseSoftmaxCrossEntropyWithLogitsOp : TF_Op<"SparseSoftmaxCrossEntropyWithLogits", [NoSideEffect]> { let summary = [{ Computes softmax cross entropy cost and gradients to backpropagate. @@ -8322,9 +8994,6 @@ are checked during execution. def TF_SplitOp : TF_Op<"Split", [NoSideEffect]> { let summary = "Splits a tensor into `num_split` tensors along one dimension."; - let description = [{ - }]; - let arguments = (ins I32Tensor:$split_dim, TF_Tensor:$value @@ -8343,9 +9012,6 @@ def TF_SplitOp : TF_Op<"Split", [NoSideEffect]> { def TF_SplitVOp : TF_Op<"SplitV", [NoSideEffect]> { let summary = "Splits a tensor into `num_split` tensors along one dimension."; - let description = [{ - }]; - let arguments = (ins TF_Tensor:$value, TF_I32OrI64Tensor:$size_splits, @@ -8409,16 +9075,15 @@ I.e., \\(y = x * x = x^2\\). }]; let arguments = (ins - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$x + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$x ); let results = (outs - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$y + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$y ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_SquaredDifferenceOp : TF_Op<"SquaredDifference", [Commutative, NoSideEffect, ResultsBroadcastableShape]>, @@ -8482,9 +9147,6 @@ shape(squeeze(t, [2, 4])) ==> [1, 2, 3, 1] def TF_StackCloseV2Op : TF_Op<"StackCloseV2", []> { let summary = "Delete the stack from its resource container."; - let description = [{ - }]; - let arguments = (ins TF_ResourceTensor:$handle ); @@ -8495,9 +9157,6 @@ def TF_StackCloseV2Op : TF_Op<"StackCloseV2", []> { def TF_StackPopV2Op : TF_Op<"StackPopV2", []> { let summary = "Pop the element at the top of the stack."; - let description = [{ - }]; - let arguments = (ins TF_ResourceTensor:$handle ); @@ -8512,9 +9171,6 @@ def TF_StackPopV2Op : TF_Op<"StackPopV2", []> { def TF_StackPushV2Op : TF_Op<"StackPushV2", []> { let summary = "Push an element onto the stack."; - let description = [{ - }]; - let arguments = (ins TF_ResourceTensor:$handle, TF_Tensor:$elem, @@ -8532,9 +9188,6 @@ def TF_StackPushV2Op : TF_Op<"StackPushV2", []> { def TF_StackV2Op : TF_Op<"StackV2", []> { let summary = "A stack that produces elements in first-in last-out order."; - let description = [{ - }]; - let arguments = (ins I32Tensor:$max_size, @@ -8547,6 +9200,32 @@ def TF_StackV2Op : TF_Op<"StackV2", []> { ); } +def TF_StatelessRandomUniformOp : TF_Op<"StatelessRandomUniform", [NoSideEffect]> { + let summary = [{ +Outputs deterministic pseudorandom random values from a uniform distribution. + }]; + + let description = [{ +The generated values follow a uniform distribution in the range `[0, 1)`. The +lower bound 0 is included in the range, while the upper bound 1 is excluded. + +The outputs are a deterministic function of `shape` and `seed`. + }]; + + let arguments = (ins + TF_I32OrI64Tensor:$shape, + TF_I32OrI64Tensor:$seed + ); + + let results = (outs + TF_FpTensor:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; + TF_DerivedOperandTypeAttr Tseed = TF_DerivedOperandTypeAttr<1>; + TF_DerivedResultTypeAttr dtype = TF_DerivedResultTypeAttr<0>; +} + def TF_StopGradientOp : TF_Op<"StopGradient", [NoSideEffect, TF_AllTypesMatch<["input", "output"]>]> { let summary = "Stops gradient computation."; @@ -8636,11 +9315,11 @@ particular, begin = [1, 2, x, x, 0, x] # x denotes don't care (usually 0) end = [2, 4, x, x, -3, x] strides = [1, 1, x, x, -1, 1] -begin_mask = 1<<4 | 1 << 5 = 48 +begin_mask = 1<<4 | 1<<5 = 48 end_mask = 1<<5 = 32 ellipsis_mask = 1<<3 = 8 -new_axis_mask = 1<<2 4 -shrink_axis_mask = 1<<0 +new_axis_mask = 1<<2 = 4 +shrink_axis_mask = 1<<0 = 1 ``` In this case if `foo.shape` is (5, 5, 5, 5, 5, 5) the final shape of @@ -8761,6 +9440,34 @@ shape of `StridedSlice`'s `input`. }]; } +def TF_StringJoinOp : TF_Op<"StringJoin", [NoSideEffect]> { + let summary = [{ +Joins the strings in the given list of string tensors into one tensor; + }]; + + let description = [{ +with the given separator (default is an empty separator). + +Examples: + +>>> s = ["hello", "world", "tensorflow"] +>>> tf.strings.join(s, " ") + + }]; + + let arguments = (ins + Variadic:$inputs, + + StrAttr:$separator + ); + + let results = (outs + TF_StrTensor:$output + ); + + TF_DerivedOperandSizeAttr N = TF_DerivedOperandSizeAttr<0>; +} + def TF_SubOp : TF_Op<"Sub", [NoSideEffect, ResultsBroadcastableShape]>, WithBroadcastableBinOpBuilder { let summary = "Returns x - y element-wise."; @@ -8781,9 +9488,7 @@ def TF_SubOp : TF_Op<"Sub", [NoSideEffect, ResultsBroadcastableShape]>, TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; -// let hasFolder = 1; } def TF_SumOp : TF_Op<"Sum", [NoSideEffect]> { @@ -8962,7 +9667,8 @@ The above computation has a replicated input of two replicas. Variadic:$inputs, DefaultValuedAttr:$is_mirrored_variable, - DefaultValuedAttr:$index + DefaultValuedAttr:$index, + DefaultValuedAttr:$is_packed ); let results = (outs @@ -9039,11 +9745,11 @@ Given an input tensor, this function computes tangent of every }]; let arguments = (ins - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$x + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$x ); let results = (outs - TensorOf<[BF16, F16, F32, F64, I32, I64, TF_Complex128, TF_Complex64]>:$y + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64]>:$y ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; @@ -9225,9 +9931,6 @@ calculation gets its own TensorArray accumulator. def TF_TensorArrayReadV3Op : TF_Op<"TensorArrayReadV3", []> { let summary = "Read an element from the TensorArray into output `value`."; - let description = [{ - }]; - let arguments = (ins TF_ResourceTensor:$handle, I32Tensor:$index, @@ -9267,9 +9970,6 @@ Scatter the data from the input value into specific TensorArray elements. def TF_TensorArraySizeV3Op : TF_Op<"TensorArraySizeV3", []> { let summary = "Get the current size of the TensorArray."; - let description = [{ - }]; - let arguments = (ins TF_ResourceTensor:$handle, F32Tensor:$flow_in @@ -9346,9 +10046,6 @@ Write data via Write and read via Read or Pack. def TF_TensorArrayWriteV3Op : TF_Op<"TensorArrayWriteV3", []> { let summary = "Push an element onto the tensor_array."; - let description = [{ - }]; - let arguments = (ins TF_ResourceTensor:$handle, I32Tensor:$index, @@ -9413,7 +10110,6 @@ input_handle: the list TF_DerivedResultTypeAttr shape_type = TF_DerivedResultTypeAttr<0>; -// let hasFolder = 1; } def TF_TensorListFromTensorOp : TF_Op<"TensorListFromTensor", [NoSideEffect]> { @@ -9469,9 +10165,6 @@ values: The tensor. def TF_TensorListGetItemOp : TF_Op<"TensorListGetItem", [NoSideEffect]> { let summary = ""; - let description = [{ - }]; - let arguments = (ins TF_VariantTensor:$input_handle, I32Tensor:$index, @@ -9601,9 +10294,6 @@ output_handle: The TensorList. def TF_TensorListSetItemOp : TF_Op<"TensorListSetItem", [NoSideEffect]> { let summary = ""; - let description = [{ - }]; - let arguments = (ins TF_VariantTensor:$input_handle, I32Tensor:$index, @@ -9834,7 +10524,6 @@ as true/false for a branch condition. value); }]>]; -// let hasCanonicalizer = 1; } def TF_TopKV2Op : TF_Op<"TopKV2", [NoSideEffect]> { @@ -9901,7 +10590,6 @@ The output `y` has the same rank as `x`. The shapes of `x` and `y` satisfy: return Verify(*this); }]; -// let hasFolder = 1; } def TF_TruncateDivOp : TF_Op<"TruncateDiv", [NoSideEffect, ResultsBroadcastableShape]>, @@ -9929,7 +10617,6 @@ Python Semantics. TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_TruncateModOp : TF_Op<"TruncateMod", [NoSideEffect, ResultsBroadcastableShape]>, @@ -10258,6 +10945,21 @@ tf.unsorted_segment_sum(c, tf.constant([0, 1, 0]), num_segments=2) let verifier = [{ return VerifyUnsortedSegmentReduction(*this); }]; } +def TF_VarIsInitializedOp : TF_Op<"VarIsInitializedOp", []> { + let summary = [{ +Checks whether a resource handle-based variable has been initialized. + }]; + + let arguments = (ins + TF_ResourceTensor:$resource + ); + + let results = (outs + I1Tensor:$is_initialized + ); + +} + def TF_VariableShapeOp : TF_Op<"VariableShape", []> { let summary = "Returns the shape of the variable pointed to by `resource`."; @@ -10286,7 +10988,6 @@ shape(t) ==> [2, 2, 3] return Verify(*this); }]; -// let hasFolder = 1; } def TF_VariableV2Op : TF_Op<"VariableV2", []> { @@ -10393,9 +11094,6 @@ def TF_XdivyOp : TF_Op<"Xdivy", [NoSideEffect, ResultsBroadcastableShape]>, WithBroadcastableBinOpBuilder { let summary = "Returns 0 if x == 0, and x / y otherwise, elementwise."; - let description = [{ - }]; - let arguments = (ins TensorOf<[F16, F32, F64, TF_Complex128, TF_Complex64]>:$x, TensorOf<[F16, F32, F64, TF_Complex128, TF_Complex64]>:$y @@ -10407,7 +11105,6 @@ def TF_XdivyOp : TF_Op<"Xdivy", [NoSideEffect, ResultsBroadcastableShape]>, TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; -// let hasCanonicalizer = 1; } def TF_XlaBroadcastHelperOp : TF_Op<"XlaBroadcastHelper", [NoSideEffect]> { @@ -10572,9 +11269,6 @@ def TF_XlaHostComputeOp : TF_Op<"XlaHostCompute", []> { A pseudo-op to represent host-side computation in an XLA program. }]; - let description = [{ - }]; - let arguments = (ins Variadic:$inputs, @@ -10645,9 +11339,6 @@ https://www.tensorflow.org/performance/xla/operation_semantics#pad def TF_XlaRecvFromHostOp : TF_Op<"XlaRecvFromHost", []> { let summary = "An op to receive a tensor from the host."; - let description = [{ - }]; - let arguments = (ins TF_ShapeAttr:$shape, StrAttr:$key @@ -10685,9 +11376,6 @@ https://www.tensorflow.org/performance/xla/operation_semantics#reduce . def TF_XlaReplicaIdOp : TF_Op<"XlaReplicaId", [NoSideEffect]> { let summary = "Replica ID."; - let description = [{ - }]; - let arguments = (ins); let results = (outs @@ -10727,9 +11415,6 @@ i=0...N-1. def TF_XlaSendToHostOp : TF_Op<"XlaSendToHost", []> { let summary = "An op to send a tensor to the host."; - let description = [{ - }]; - let arguments = (ins TF_Tensor:$input, @@ -10773,9 +11458,6 @@ tensor such that tensor[...,:,:] = u[..., :, :] * Diag(s[..., :]) * Transpose(v[ def TF_Xlog1pyOp : TF_Op<"Xlog1py", [NoSideEffect]> { let summary = "Returns 0 if x == 0, and x * log1p(y) otherwise, elementwise."; - let description = [{ - }]; - let arguments = (ins TensorOf<[F16, F32, F64, TF_Complex128, TF_Complex64]>:$x, TensorOf<[F16, F32, F64, TF_Complex128, TF_Complex64]>:$y @@ -10792,9 +11474,6 @@ def TF_XlogyOp : TF_Op<"Xlogy", [NoSideEffect, ResultsBroadcastableShape]>, WithBroadcastableBinOpBuilder { let summary = "Returns 0 if x == 0, and x * log(y) otherwise, elementwise."; - let description = [{ - }]; - let arguments = (ins TensorOf<[F16, F32, F64, TF_Complex128, TF_Complex64]>:$x, TensorOf<[F16, F32, F64, TF_Complex128, TF_Complex64]>:$y @@ -10810,26 +11489,112 @@ def TF_XlogyOp : TF_Op<"Xlogy", [NoSideEffect, ResultsBroadcastableShape]>, def TF_ZerosLikeOp : TF_Op<"ZerosLike", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Returns a tensor of zeros with the same shape and type as x."; + let arguments = (ins + TF_Tensor:$x + ); + + let results = (outs + TF_Tensor:$y + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + +def TF__FusedConv2DOp : TF_Op<"_FusedConv2D", [NoSideEffect]> { + let summary = [{ +Performs a convolution followed by a specified series of operations. + }]; + let description = [{ +The inputs to the convolution are `input` and `filter`. The series of operations +that follows is specified by the `fused_ops` attribute, which is a list of TF op +names specified as strings (e.g. "Relu"). They are performed in order, where the +(first) input to each op is the output of the preceding op. The first input and +the output of each fused_op must be of type T. + +Currently supported fused_op combinations are: [X] and [X,A], where X is one of +{"BiasAdd","FusedBatchNorm"} and A is one of {"Elu","Relu","Relu6"}. + +* The first input to op X is the Conv2D result, and the additional input(s) to X +are specified by `args`. +* If there is an op A specified, the output of op X is the input to op A, and op +A produces the _FusedConv2D output. Otherwise, op X produces the _FusedConv2D +output. + +*NOTE*: Do not invoke this operator directly in Python. Grappler is expected to +create these operators. }]; let arguments = (ins - TF_Tensor:$x + TF_F32OrF64Tensor:$input, + TF_F32OrF64Tensor:$filter, + Variadic:$args, + + I64ArrayAttr:$strides, + TF_AnyStrAttrOf<["SAME", "VALID", "EXPLICIT"]>:$padding, + DefaultValuedAttr:$explicit_paddings, + DefaultValuedAttr:$data_format, + DefaultValuedAttr:$dilations, + DefaultValuedAttr:$use_cudnn_on_gpu, + DefaultValuedAttr:$fused_ops, + DefaultValuedAttr:$epsilon ); let results = (outs - TF_Tensor:$y + TF_F32OrF64Tensor:$output ); TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; + TF_DerivedOperandSizeAttr num_args = TF_DerivedOperandSizeAttr<2>; } -def TF__HostComputeMlirOp : TF_Op<"_HostComputeMlir", []> { - let summary = "A host-side computation called from a TPU device."; +def TF__FusedMatMulOp : TF_Op<"_FusedMatMul", [NoSideEffect]> { + let summary = [{ +Performs a MatMul followed by a specified series of operations. + }]; let description = [{ +The inputs to the MatMul are specified by `a` and `b`. The series of operations +that follows is specified by the `fused_ops` attribute, which is a list of TF op +names specified as strings (e.g. "Relu"). They are performed in order, where the +(first) input to each op is the output of the preceding op. The first input and +the output of each fused_op must be of type T. + +Currently supported fused_op combinations are: ["BiasAdd"] and ["BiasAdd",A], +where A is one of {"Elu","Relu","Relu6"}. + +* The first input to BiasAdd is the Conv2D result, and the additional BiasAdd +input is specified by `args`. +* If there is an op A specified, the output of the BiasAdd is the input to op A, +and op A produces the _FusedConv2D output. Otherwise, the BiasAdd produces the +_FusedConv2D output. + +*NOTE*: Do not invoke this operator directly in Python. Grappler is +expected to create these operators. }]; + let arguments = (ins + F32Tensor:$a, + F32Tensor:$b, + Variadic:$args, + + DefaultValuedAttr:$transpose_a, + DefaultValuedAttr:$transpose_b, + DefaultValuedAttr:$fused_ops, + DefaultValuedAttr:$epsilon + ); + + let results = (outs + F32Tensor:$product + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; + TF_DerivedOperandSizeAttr num_args = TF_DerivedOperandSizeAttr<2>; +} + +def TF__HostComputeMlirOp : TF_Op<"_HostComputeMlir", []> { + let summary = "A host-side computation called from a TPU device."; + let arguments = (ins Variadic:$inputs, @@ -10909,9 +11674,6 @@ def TF__XlaRecvAtHostOp : TF_Op<"_XlaRecvAtHost", []> { A placeholder op to receive values from a running XLA computation. }]; - let description = [{ - }]; - let arguments = (ins TF_StrTensor:$dynamic_key, @@ -10929,9 +11691,6 @@ A placeholder op to receive values from a running XLA computation. def TF__XlaSendFromHostOp : TF_Op<"_XlaSendFromHost", []> { let summary = "A placeholder op to send values to a running XLA computation."; - let description = [{ - }]; - let arguments = (ins Variadic:$inputs, TF_StrTensor:$dynamic_key, diff --git a/tools/mlir/tf_op_base.td b/tools/mlir/tf_op_base.td index 3150fde1f..f369b312e 100644 --- a/tools/mlir/tf_op_base.td +++ b/tools/mlir/tf_op_base.td @@ -80,6 +80,26 @@ class TF_AllTypesMatch names> : TF_AllTypesMatchPred< !foreach(n, names, !subst("$_self", "$" # n, "$_self.getType()"))>>; +//===----------------------------------------------------------------------===// +// TensorFlow op side effects +//===----------------------------------------------------------------------===// + +class TF_ResourceBase : + Resource { +} + +def TF_VariableResource : TF_ResourceBase<"Variable">; +def TF_StackResource : TF_ResourceBase<"Stack">; +def TF_TensorArrayResource : TF_ResourceBase<"TensorArray">; + +def TF_VariableRead : MemRead; +def TF_StackRead : MemRead; +def TF_TensorArrayRead : MemRead; + +def TF_VariableWrite : MemWrite; +def TF_StackWrite : MemWrite; +def TF_TensorArrayWrite : MemWrite; + //===----------------------------------------------------------------------===// // TensorFlow op definitions //===----------------------------------------------------------------------===// diff --git a/tools/mlir/tf_ops.td b/tools/mlir/tf_ops.td index f71f05a28..897dc8352 100644 --- a/tools/mlir/tf_ops.td +++ b/tools/mlir/tf_ops.td @@ -31,6 +31,7 @@ include "tf_generated_ops.td" include "tf_op_base.td" include "mlir/Interfaces/CallInterfaces.td" include "mlir/Interfaces/InferTypeOpInterface.td" +include "mlir/Interfaces/LoopLikeInterface.td" include "mlir/IR/OpBase.td" class TF_TensorListInitOp : TF_Op { @@ -90,7 +91,6 @@ def TF_ConstOp : TF_Op<"Const", [ConstantLike, NoSideEffect, "OpBuilder &builder, OperationState &result, Type type, Attribute value">, ]; -// let hasFolder = 1; let extraClassDeclaration = [{ static bool isCompatibleReturnTypes(ArrayRef l, ArrayRef r) { @@ -99,6 +99,30 @@ def TF_ConstOp : TF_Op<"Const", [ConstantLike, NoSideEffect, }]; } +def TF_CollectivePermuteOp : TF_Op<"CollectivePermute", []> { + let summary = "An Op to permute tensors across replicated TPU instances."; + + let description = [{ +Each instance supplies its own input. + +For example, suppose there are 4 TPU instances: `[A, B, C, D]`. Passing +source_target_pairs=`[[0,1],[1,2],[2,3],[3,0]]` gets the outputs: +`[D, A, B, C]`. + }]; + + let arguments = (ins + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$input, + I32Tensor:$source_target_pairs + ); + + let results = (outs + TensorOf<[BF16, F16, F32, F64, I16, I32, I64, I8, TF_Complex128, TF_Complex64, TF_Qint32, TF_Qint8, TF_Quint8, TF_Uint16, TF_Uint32, TF_Uint64, TF_Uint8]>:$output + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + + def TF_DataFormatVecPermuteOp : TF_Op<"DataFormatVecPermute", [NoSideEffect, SameOperandsAndResultType]> { let summary = "Permute input tensor from `src_format` to `dst_format`"; @@ -206,8 +230,10 @@ else_branch: A function that takes 'inputs' and returns a list of }]; } -def TF_YieldOp : TF_Op<"Yield", [Terminator]> { +def TF_YieldOp : TF_Op<"Yield", + [Terminator, ParentOneOf<["IfRegionOp", "WhileRegionOp"]>]> { let summary = "Yield operation"; + let description = [{ The "yield" operation represents a return operation within the conditional and body of structured control flow (e.g., if and while). The operation @@ -217,10 +243,6 @@ def TF_YieldOp : TF_Op<"Yield", [Terminator]> { }]; let arguments = (ins Variadic:$operands); - - let verifier = [{ - return Verify(*this); - }]; } def TF_IfRegionOp : TF_Op<"IfRegion", @@ -294,7 +316,6 @@ retained with length 1. // TF_FoldOperandsTransposeInterface: SmallVector GetLayoutDependentArgs() { return {0}; } SmallVector GetLayoutDependentResults() { return {}; } - LogicalResult FoldOperandsPermutation(ArrayRef permutation); }]; } @@ -334,6 +355,41 @@ def TF_LegacyCallOp : TF_Op<"LegacyCall", }]; } +def TF_ParseExampleOp : TF_Op<"ParseExample", + [NoSideEffect, + AttrSizedResultSegments, + AttrSizedOperandSegments]> { + + let summary = + "Transforms a vector of tf.Example protos (as strings) into typed tensors."; + + let arguments = (ins + TF_StrTensor:$serialized, + TF_StrTensor:$names, + Variadic:$sparse_keys, + Variadic:$dense_keys, + Variadic>:$dense_defaults, + + TF_ShapeAttrArray:$dense_shapes, + I32ElementsAttr:$result_segment_sizes, + I32ElementsAttr:$operand_segment_sizes + ); + + let results = (outs + Variadic:$sparse_indices, // len(sparse_types) + Variadic>:$sparse_values, // len(sparse_types) + Variadic:$sparse_shapes, // len(sparse_types) + Variadic>:$dense_values // len(Tdense) + ); + + TF_DerivedOperandSizeAttr Nsparse = TF_DerivedOperandSizeAttr<2>; + TF_DerivedOperandSizeAttr Ndense = TF_DerivedOperandSizeAttr<3>; + TF_DerivedOperandTypeListAttr Tdense = TF_DerivedOperandTypeListAttr<4>; + TF_DerivedResultTypeListAttr sparse_types = TF_DerivedResultTypeListAttr<1>; + + let verifier = ?; +} + def TF_ParseExampleV2Op : TF_Op<"ParseExampleV2", [NoSideEffect, AttrSizedResultSegments]> { @@ -438,6 +494,7 @@ Inserts a placeholder for a tensor that will be always fed. def TF_PlaceholderWithDefaultOp : TF_Op<"PlaceholderWithDefault", [NoSideEffect]> { let summary = "Placeholder op"; + let description = [{ A placeholder op that passes through input when its output is not fed. }]; @@ -534,7 +591,7 @@ output = input; While (Cond(output)) { output = Body(output) } input: A list of input tensors whose types are T. output: A list of output tensors whose types are T. -cond: A function takes 'input' and returns a tensor. If the tensor is +cond: A function that takes 'input' and returns a tensor. If the tensor is a scalar of non-boolean, the scalar is converted to a boolean according to the following rule: if the scalar is a numerical value, non-zero means True and zero means False; if the scalar is @@ -570,6 +627,58 @@ body: A function that takes a list of tensors and returns another }]; } +def TL_WhileRegionOp : TF_Op<"WhileRegion", + [DeclareOpInterfaceMethods, + SingleBlockImplicitTerminator<"YieldOp">]> { + let summary = "while operation"; + let description = [{ + The tf.WhileRegion op represents a while loop using 2 regions and a set of + iteration variables. The iteration variables maintained by this Op have the + same types as the inputs. The Op executes a while loop described by the + following pseudo code: + + ``` + func WhileRegionOp(inputs) { + iteration_vars = inputs; + while (cond(iteration_vars)) { + iteration_vars = body(iteration_vars); + } + return iteration_vars; + } + ``` + + `cond` is the condition region and `body` is the body region. Both these + regions accept the current value of the iteration variables as inputs. The + condition region returns a tensor which, if false, will exit the loop. + The body region computes new values of the iteration variables. The iteration + variables are initialized to the Op input, and the results of the + tf.WhileRegion op are the final values of the iteration variables. + + This implies that the operand and result types for tf.WhileRegion should be + the same. Note that the condition and body regions can implicitly capture + loop invariant values directly. In canonical form, iteration variables that + pass through the loop body unmodified are converted to implicitly captured + references to their values outside the loop. + }]; + + let arguments = (ins + Variadic:$input, + + // Used to map StatelessWhile and While op defined in TensorFlow to a common + // op. + DefaultValuedAttr:$is_stateless, + DefaultValuedAttr:$parallel_iterations + ); + let results = (outs Variadic:$output); + + TF_DerivedOperandTypeListAttr T = TF_DerivedOperandTypeListAttr<0>; + + let regions = (region SizedRegion<1>:$cond, SizedRegion<1>:$body); + + let verifier = [{ return Verify(*this); }]; + +} + def TF_TensorListReserveOp : TF_TensorListInitOp<"TensorListReserve"> { let summary = "List of the given size with empty elements."; @@ -609,7 +718,8 @@ This operation holds the metadata common to operations of a `tpu.replicate()` co DefaultValuedAttr:$host_compute_core, DefaultValuedAttr:$padding_map, DefaultValuedAttr:$step_marker_location, - DefaultValuedAttr:$allow_soft_placement + DefaultValuedAttr:$allow_soft_placement, + DefaultValuedAttr:$use_spmd_for_xla_partitioning ); let results = (outs); @@ -780,9 +890,6 @@ def TF_XlaShardingOp : TF_Op<"XlaSharding", [NoSideEffect]> { An op which shards the input based on the given sharding attribute. }]; - let description = [{ - }]; - let arguments = (ins TF_Tensor:$input, @@ -799,9 +906,6 @@ An op which shards the input based on the given sharding attribute. def TF_InfeedDequeueTupleOp : TF_Op<"InfeedDequeueTuple", []> { let summary = "Fetches multiple values from infeed as an XLA tuple."; - let description = [{ - }]; - let arguments = (ins OptionalAttr:$_XlaSharding ); @@ -845,9 +949,6 @@ def TF_BatchDatasetV2Op : TF_Op<"BatchDatasetV2", [NoSideEffect]> { Creates a dataset that batches `batch_size` elements from `input_dataset`. }]; - let description = [{ - }]; - let arguments = (ins TF_VariantTensor:$input_dataset, I64Tensor:$batch_size, @@ -989,4 +1090,76 @@ operation create / operate on a copy of `x`. TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; } +def TF_BesselI0eOp : TF_Op<"BesselI0e", [NoSideEffect, SameOperandsAndResultType]> { + let summary = "Computes the Bessel i0e function of `x` element-wise."; + + let description = [{ +Exponentially scaled modified Bessel function of order 0 defined as +`bessel_i0e(x) = exp(-abs(x)) bessel_i0(x)`. + +This function is faster and numerically stabler than `bessel_i0(x)`. + }]; + + let arguments = (ins + TF_FpTensor:$x + ); + + let results = (outs + TF_FpTensor:$y + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + +def TF_BesselI1eOp : TF_Op<"BesselI1e", [NoSideEffect, SameOperandsAndResultType]> { + let summary = "Computes the Bessel i1e function of `x` element-wise."; + + let description = [{ +Exponentially scaled modified Bessel function of order 0 defined as +`bessel_i1e(x) = exp(-abs(x)) bessel_i1(x)`. + +This function is faster and numerically stabler than `bessel_i1(x)`. + }]; + + let arguments = (ins + TF_FpTensor:$x + ); + + let results = (outs + TF_FpTensor:$y + ); + + TF_DerivedOperandTypeAttr T = TF_DerivedOperandTypeAttr<0>; +} + +def TF_StringToHashBucketFastOp : TF_Op<"StringToHashBucketFast", [NoSideEffect]> { + let summary = [{ +Converts each string in the input Tensor to its hash mod by a number of buckets. + }]; + + let description = [{ +The hash function is deterministic on the content of the string within the +process and will never change. However, it is not suitable for cryptography. +This function may be used when CPU time is scarce and inputs are trusted or +unimportant. There is a risk of adversaries constructing inputs that all hash +to the same bucket. To prevent this problem, use a strong hash function with +`tf.string_to_hash_bucket_strong`. + +Examples: + +>>> tf.strings.to_hash_bucket_fast(["Hello", "TensorFlow", "2.x"], 3).numpy() +array([0, 2, 2]) + }]; + + let arguments = (ins + TF_StrTensor:$input, + + Confined]>:$num_buckets + ); + + let results = (outs + I64Tensor:$output + ); +} + #endif // TF_OPS diff --git a/tools/mlir/tf_side_effects.h b/tools/mlir/tf_side_effects.h new file mode 100644 index 000000000..fc9e6631f --- /dev/null +++ b/tools/mlir/tf_side_effects.h @@ -0,0 +1,54 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This is the side effect definition file for TensorFlow. +#ifndef TENSORFLOW_COMPILER_MLIR_TENSORFLOW_IR_TF_SIDE_EFFECTS_H_ +#define TENSORFLOW_COMPILER_MLIR_TENSORFLOW_IR_TF_SIDE_EFFECTS_H_ + +#include "mlir/Interfaces/SideEffectInterfaces.h" // from @llvm-project + +namespace mlir { +namespace TF { +namespace ResourceEffects { + +struct Variable : ::mlir::SideEffects::Resource::Base +{ + StringRef getName() final + { + return "Variable"; + } +}; + +struct Stack : ::mlir::SideEffects::Resource::Base +{ + StringRef getName() final + { + return "Stack"; + } +}; + +struct TensorArray : ::mlir::SideEffects::Resource::Base +{ + StringRef getName() final + { + return "TensorArray"; + } +}; + +} // namespace ResourceEffects +} // namespace TF +} // namespace mlir + +#endif // TENSORFLOW_COMPILER_MLIR_TENSORFLOW_IR_TF_SIDE_EFFECTS_H_ diff --git a/tools/mlir/tf_types.h b/tools/mlir/tf_types.h index aa7ec6e7a..a0cb969c8 100644 --- a/tools/mlir/tf_types.h +++ b/tools/mlir/tf_types.h @@ -115,10 +115,11 @@ namespace detail { // - `static unsigned getTypeKind()` that returns the (fixed) kind of the // type. template -class TensorFlowTypeImpl : public Type::TypeBase +class TensorFlowTypeImpl + : public Type::TypeBase { public: - using Base = typename Type::TypeBase; + using Base = typename Type::TypeBase; using TFBase = TensorFlowTypeImpl; using Base::Base;