| 32 | explicit FillOp(OpKernelConstruction* ctx) : XlaOpKernel(ctx) {} |
| 33 | |
| 34 | void Compile(XlaOpKernelContext* ctx) override { |
| 35 | // The output of this Op is a tensor of shape 'dims_shape' with each |
| 36 | // element set to the scalar 'dims_literal'. |
| 37 | const TensorShape dims_shape = ctx->InputShape("dims"); |
| 38 | const TensorShape value_shape = ctx->InputShape("value"); |
| 39 | OP_REQUIRES( |
| 40 | ctx, TensorShapeUtils::IsVector(dims_shape), |
| 41 | errors::InvalidArgument("dims must be a vector of int32, got shape ", |
| 42 | dims_shape.DebugString())); |
| 43 | OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(value_shape), |
| 44 | errors::InvalidArgument("value must be a scalar, got shape ", |
| 45 | value_shape.DebugString())); |
| 46 | |
| 47 | std::vector<int64> dims; |
| 48 | OP_REQUIRES_OK(ctx, ctx->ConstantInputAsIntVector("dims", &dims)); |
| 49 | // Set dynamic dimension value to -1 so that we know which dimension is |
| 50 | // dynamic. |
| 51 | ctx->set_dynamic_dimension_is_minus_one(true); |
| 52 | std::vector<int64> dynamic_dims; |
| 53 | OP_REQUIRES_OK(ctx, ctx->ConstantInputAsIntVector("dims", &dynamic_dims)); |
| 54 | |
| 55 | auto output = xla::Broadcast(ctx->Input("value"), dims); |
| 56 | for (int64 i = 0; i < dims.size(); ++i) { |
| 57 | // If a dimension is dynamic, call set-dimension-size on the output. |
| 58 | if (dynamic_dims[i] == -1) { |
| 59 | auto dynamic_dim_size = xla::Slice(ctx->Input(0), {i}, {i + 1}, {1}); |
| 60 | dynamic_dim_size = xla::Reshape(dynamic_dim_size, {}); |
| 61 | dynamic_dim_size = xla::ConvertElementType(dynamic_dim_size, xla::S32); |
| 62 | output = xla::SetDimensionSize(output, dynamic_dim_size, i); |
| 63 | } |
| 64 | } |
| 65 | ctx->SetOutput(0, output); |
| 66 | } |
| 67 | }; |
| 68 | |
| 69 | REGISTER_XLA_OP(Name("Fill").CompileTimeConstantInput("dims"), FillOp); |
nothing calls this directly
no test coverage detected