blob: a9d994c2a883db304615047beedd031132e4ec01 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/*!
* \brief Registration of transform operators
* \file transform.cc
*/
#include <tvm/ffi/function.h>
#include <tvm/ffi/reflection/registry.h>
#include <tvm/topi/einsum.h>
#include <tvm/topi/transform.h>
#include <tvm/topi/utils.h>
#include <iostream>
#include "tvm/ir/expr.h"
namespace tvm {
namespace topi {
using namespace tvm;
using namespace tvm::runtime;
TVM_FFI_STATIC_INIT_BLOCK() {
namespace refl = tvm::ffi::reflection;
refl::GlobalDef()
.def_packed("topi.expand_dims",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = expand_dims(args[0].cast<te::Tensor>(), args[1].cast<int>(),
args[2].cast<int>());
})
.def_packed("topi.transpose",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = transpose(args[0].cast<te::Tensor>(),
args[1].cast<ffi::Optional<ffi::Array<int64_t>>>());
})
.def_packed("topi.flip",
[](ffi::PackedArgs args, ffi::Any* rv) {
// pass empty seq_lengths tensor to reverse_sequence
*rv = reverse_sequence(args[0].cast<te::Tensor>(), te::Tensor(),
args[1].cast<int>());
})
.def_packed("topi.reverse_sequence",
[](ffi::PackedArgs args, ffi::Any* rv) {
int batch_axis = args.size() >= 4 ? args[3].cast<int>() : 0;
*rv = reverse_sequence(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(),
args[2].cast<int>(), batch_axis);
})
.def_packed("topi.reshape",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = reshape(args[0].cast<te::Tensor>(), args[1].cast<ffi::Array<PrimExpr>>());
})
.def_packed("topi.sliding_window",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = sliding_window(args[0].cast<te::Tensor>(), args[1].cast<int>(),
args[2].cast<ffi::Array<int64_t>>(),
args[3].cast<ffi::Array<int64_t>>());
})
.def_packed("topi.squeeze",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = squeeze(args[0].cast<te::Tensor>(), ArrayOrInt(args[1]));
})
.def_packed("topi.concatenate",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = concatenate(args[0].cast<ffi::Array<te::Tensor>>(), args[1].cast<int>());
})
.def_packed("topi.stack",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = stack(args[0].cast<ffi::Array<te::Tensor>>(), args[1].cast<int>());
})
.def_packed("topi.shape",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = shape(args[0].cast<te::Tensor>(), args[1].cast<PrimType>());
})
.def_packed("topi.tensor_size",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = tensor_size(args[0].cast<te::Tensor>(), args[1].cast<PrimType>());
})
.def_packed("topi.split",
[](ffi::PackedArgs args, ffi::Any* rv) {
if (args[1].try_cast<int>()) {
*rv = split_n_sections(args[0].cast<te::Tensor>(), args[1].cast<int>(),
args[2].cast<int>());
} else {
*rv = split_indices_array(args[0].cast<te::Tensor>(),
args[1].cast<ffi::Array<PrimExpr>>(),
args[2].cast<int>());
}
})
.def_packed("topi.layout_transform",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv =
layout_transform(args[0].cast<te::Tensor>(), args[1].cast<std::string>(),
args[2].cast<std::string>(), args[3].cast<std::string>());
})
.def_packed(
"topi.take",
[](ffi::PackedArgs args, ffi::Any* rv) {
if (args.size() == 4) {
auto mode = args[3].cast<std::string>();
int batch_dims = args[2].cast<int>();
*rv = take(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), batch_dims, mode);
} else {
TVM_FFI_ICHECK_EQ(args.size(), 5) << "topi.take expects 4 or 5 arguments";
int batch_dims = args[2].cast<int>();
int axis = args[3].cast<int>();
auto mode = args[4].cast<std::string>();
*rv =
take(args[0].cast<te::Tensor>(),
args[1].cast<ffi::Variant<te::Tensor, PrimExpr>>(), batch_dims, axis, mode);
}
})
.def_packed("topi.sequence_mask",
[](ffi::PackedArgs args, ffi::Any* rv) {
double pad_val = args[2].cast<double>();
int axis = args[3].cast<int>();
*rv = sequence_mask(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(),
pad_val, axis);
})
.def_packed("topi.where",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = where(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(),
args[2].cast<te::Tensor>());
})
.def_packed("topi.arange",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = arange(args[0].cast<PrimExpr>(), args[1].cast<PrimExpr>(),
args[2].cast<PrimExpr>(), args[3].cast<PrimType>());
})
.def_packed("topi.meshgrid",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = meshgrid(args[0].cast<ffi::Array<te::Tensor>>(),
args[1].cast<std::string>());
})
.def_packed("topi.repeat",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = repeat(args[0].cast<te::Tensor>(), args[1].cast<int>(),
args[2].cast<int>());
})
.def_packed("topi.tile",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = tile(args[0].cast<te::Tensor>(), args[1].cast<ffi::Array<int64_t>>());
})
.def_packed("topi.dyn_tile",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = dyn_tile(args[0].cast<te::Tensor>(), args[1].cast<ffi::Array<PrimExpr>>(),
args[2].cast<int>());
})
.def_packed("topi.gather",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = gather(args[0].cast<te::Tensor>(), args[1].cast<int>(),
args[2].cast<te::Tensor>());
})
.def_packed("topi.gather_nd",
[](ffi::PackedArgs args, ffi::Any* rv) {
int batch_dims = args[2].cast<int>();
*rv = gather_nd(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(),
batch_dims);
})
.def_packed("topi.unravel_index",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = unravel_index(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>());
})
.def_packed("topi.sparse_to_dense",
[](ffi::PackedArgs args, ffi::Any* rv) {
*rv = sparse_to_dense(args[0].cast<te::Tensor>(),
args[1].cast<ffi::Array<PrimExpr>>(),
args[2].cast<te::Tensor>(), args[3].cast<PrimExpr>());
})
.def_packed("topi.matmul",
[](ffi::PackedArgs args, ffi::Any* rv) {
switch (args.size()) {
case 2:
*rv = matmul(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>());
break;
case 3:
*rv = matmul(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(),
args[2].cast<bool>());
break;
case 4:
*rv = matmul(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(),
args[2].cast<bool>(), args[3].cast<bool>());
break;
default:
TVM_FFI_ICHECK(0) << "topi.matmul expects 2, 3 or 4 arguments";
}
})
.def_packed("topi.tensordot",
[](ffi::PackedArgs args, ffi::Any* rv) {
if (args.size() == 2) {
*rv = tensordot(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>());
} else if (args.size() == 3) {
*rv = tensordot(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(),
args[2].cast<int>());
} else {
ffi::Array<PrimExpr> axes = args[3].cast<ffi::Array<PrimExpr>>();
*rv = tensordot(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(),
args[2].cast<ffi::Array<PrimExpr>>(), axes);
}
})
.def_packed(
"topi.strided_slice",
[](ffi::PackedArgs args, ffi::Any* rv) {
te::Tensor x = args[0].cast<te::Tensor>();
ffi::Array<PrimExpr> begin = args[1].cast<ffi::Array<PrimExpr>>();
ffi::Array<PrimExpr> end = args[2].cast<ffi::Array<PrimExpr>>();
ffi::Array<PrimExpr> strides = args[3].cast<ffi::Array<PrimExpr>>();
ffi::Array<int64_t> axes = args[4].cast<ffi::Array<int64_t>>();
bool assume_inbound = args[6].cast<bool>();
if (IsConstIntArray(begin) && IsConstIntArray(end) && IsConstIntArray(strides) &&
IsConstIntArray(x->shape)) {
ffi::Array<ffi::Optional<IntImm>> begin_static =
args[1].cast<ffi::Array<ffi::Optional<IntImm>>>();
ffi::Array<ffi::Optional<IntImm>> end_static =
args[2].cast<ffi::Array<ffi::Optional<IntImm>>>();
ffi::Array<IntImm> strides_static = args[3].cast<ffi::Array<IntImm>>();
auto slice_mode = args[5].cast<std::string>();
if (axes.size()) {
*rv = strided_slice_with_axes(x, begin_static, end_static, strides_static, axes,
slice_mode);
} else {
*rv = strided_slice(x, begin_static, end_static, strides_static, slice_mode);
}
} else {
if (axes.size()) {
*rv = dynamic_strided_slice_with_axes(x, begin, end, strides, axes, assume_inbound);
} else {
*rv = dynamic_strided_slice(x, begin, end, strides, assume_inbound);
}
}
})
.def_packed("topi.dynamic_strided_slice",
[](ffi::PackedArgs args, ffi::Any* rv) {
te::Tensor begin = args[1].cast<te::Tensor>();
te::Tensor end = args[2].cast<te::Tensor>();
te::Tensor strides = args[3].cast<te::Tensor>();
*rv = dynamic_strided_slice(args[0].cast<te::Tensor>(), begin, end, strides);
})
.def("topi.relax_dynamic_strided_slice",
[](te::Tensor x, te::Tensor begin, te::Tensor end, te::Tensor strides,
ffi::Array<PrimExpr> output_shape) {
return relax::dynamic_strided_slice(x, begin, end, strides, output_shape);
})
.def_packed("topi.one_hot",
[](ffi::PackedArgs args, ffi::Any* rv) {
int depth = args[3].cast<int>();
int axis = args[4].cast<int>();
PrimType dtype = args[5].cast<PrimType>();
*rv = one_hot(args[0].cast<te::Tensor>(), args[1].cast<PrimExpr>(),
args[2].cast<PrimExpr>(), depth, axis, dtype);
})
.def_packed("topi.matrix_set_diag",
[](ffi::PackedArgs args, ffi::Any* rv) {
int k1 = args[2].cast<int>();
int k2 = args[3].cast<int>();
bool super_diag_right_align = args[4].cast<bool>();
bool sub_diag_right_align = args[5].cast<bool>();
*rv = matrix_set_diag(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(),
k1, k2, super_diag_right_align, sub_diag_right_align);
})
.def("topi.adv_index",
[](te::Tensor x, ffi::Array<te::Tensor> indices) { return adv_index(x, indices); });
}
} // namespace topi
} // namespace tvm