tvm
strided_slice.h
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
24 #ifndef TVM_TOPI_DETAIL_STRIDED_SLICE_H_
25 #define TVM_TOPI_DETAIL_STRIDED_SLICE_H_
26 
27 #include <tvm/tirx/expr.h>
28 
29 #include <algorithm>
30 #include <limits>
31 #include <string>
32 #include <tuple>
33 #include <vector>
34 
35 #include "constant_utils.h"
36 
37 namespace tvm {
38 namespace topi {
39 namespace detail {
40 
41 using namespace tvm::te;
42 
43 inline int64_t CanonicalizeIndex(int64_t index, int64_t extent, int64_t stride) {
44  int64_t begin_range = stride < 0 ? -1 : 0;
45  int64_t end_range = stride < 0 ? extent - 1 : extent;
46  if (index < 0) {
47  index += extent;
48  }
49  return std::min(std::max(index, begin_range), end_range);
50 }
51 
52 inline std::tuple<std::vector<int64_t>, std::vector<int64_t>, std::vector<int64_t>> ConvertToVec(
53  const ffi::Array<ffi::Optional<IntImm>>& begin, const ffi::Array<ffi::Optional<IntImm>>& end,
54  const ffi::Array<IntImm>& strides, std::string slice_mode) {
55  std::vector<int64_t> stride_vec(strides.size(), 1);
56  if (slice_mode == "end") {
57  for (size_t i = 0; i < strides.size(); ++i) {
58  stride_vec[i] = strides[i]->value;
59  }
60  }
61  const int64_t max_range = std::numeric_limits<int64_t>::max();
62  std::vector<int64_t> begin_vec;
63  for (size_t i = 0; i < begin.size(); ++i) {
64  if (!begin[i].has_value()) {
65  // value=None
66  begin_vec.push_back(stride_vec[i] > 0 ? 0 : max_range);
67  } else {
68  begin_vec.push_back(begin[i].value()->value);
69  }
70  }
71  std::vector<int64_t> end_vec;
72  for (size_t i = 0; i < end.size(); ++i) {
73  // allow end to be None
74  if (!end[i].has_value()) {
75  end_vec.push_back(stride_vec[i] < 0 ? 0 : max_range);
76  } else if (slice_mode == "size") {
77  int64_t end_val = end[i].value()->value;
78  if (end_val < 0) {
79  end_vec.push_back(stride_vec[i] < 0 ? 0 : max_range);
80  } else {
81  end_vec.push_back(begin_vec[i] + end_val);
82  }
83  } else {
84  end_vec.push_back(end[i].value()->value);
85  }
86  }
87  return std::make_tuple(begin_vec, end_vec, stride_vec);
88 }
89 
90 inline ffi::Array<PrimExpr> StridedSliceCanonicalizeBegin(const ffi::Array<PrimExpr>& ishape,
91  const std::vector<int64_t>& begin,
92  const std::vector<int64_t>& strides,
93  const ffi::Array<int64_t>& axes,
94  PrimType dtype,
95  std::string slice_mode = "end") {
96  ffi::Array<PrimExpr> begin_expr;
97  for (size_t i = 0; i < axes.size(); ++i) {
98  int64_t ax = axes[i];
99  if (ishape[ax]->IsInstance<tvm::IntImmNode>()) {
100  int64_t dim_i = GetConstInt(ishape[ax]);
101  int64_t begin_i = CanonicalizeIndex(begin[i], dim_i, strides[i]);
102  begin_expr.push_back(MakeConst(dtype, begin_i));
103  } else {
104  auto idim = ishape[ax];
105  auto b_expr = MakeConst(dtype, begin[i]);
106  PrimExpr b = begin[i] < 0 ? b_expr + idim : b_expr;
107  auto s = strides[i];
108  if (s < 0) {
109  b = tvm::min(b, idim - 1);
110  } else {
111  b = tvm::if_then_else(b < 0, 0, b);
112  }
113  begin_expr.push_back(b);
114  }
115  }
116  return begin_expr;
117 }
118 
119 inline ffi::Array<PrimExpr> StridedSliceOutputShape(
120  const ffi::Array<PrimExpr>& ishape, const std::vector<int64_t>& begin,
121  const std::vector<int64_t>& end, const std::vector<int64_t>& strides,
122  const ffi::Array<int64_t>& axes, std::string slice_mode,
123  const ffi::Array<PrimExpr>& begin_canonicalized, bool use_any = false) {
124  TVM_FFI_ICHECK(!use_any) << "StridedSliceOutputShape does not legacy use_any";
125  const size_t src_tensor_dim = ishape.size();
126  ffi::Array<PrimExpr> out_shape;
127  for (size_t i = 0; i < src_tensor_dim; ++i) {
128  out_shape.push_back(ishape[i]);
129  }
130 
131  for (size_t i = 0; i < axes.size(); ++i) {
132  int64_t ax = axes[i];
133  if (ishape[ax]->IsInstance<tvm::IntImmNode>()) {
134  const int64_t dim_i = GetConstInt(ishape[ax]);
135  TVM_FFI_ICHECK(begin_canonicalized[i]->IsInstance<tvm::IntImmNode>());
136  int64_t begin_i = GetConstInt(begin_canonicalized[i]);
137  int64_t end_i = CanonicalizeIndex(end[i], dim_i, strides[i]);
138  int interval = std::abs(end_i - begin_i);
139  int slice_size =
140  static_cast<int>((interval + std::abs(strides[i]) - 1) / std::abs(strides[i]));
141  TVM_FFI_ICHECK(strides[i] < 0 ? (end_i <= begin_i) : (begin_i <= end_i))
142  << ": Input [Begin=" << begin[i] << ", End=" << end[i] << "] is invalid for axis=" << i;
143  out_shape.Set(ax, cast(out_shape[i].ty(), PrimExpr(slice_size)));
144  } else {
145  out_shape.Set(ax, tvm::tirx::PrimVar("dim", out_shape[i].ty()));
146  }
147  }
148 
149  return out_shape;
150 }
151 
152 } // namespace detail
153 } // namespace topi
154 } // namespace tvm
155 #endif // TVM_TOPI_DETAIL_STRIDED_SLICE_H_
Checked scalar view over a VarNode.
Definition: var.h:127
Utility functions for handling constants in TVM expressions.
Tensor expression language DSL.
Definition: extracted_task.h:32
PrimExpr MakeConst(PrimType dtype, ValueType value, Span span=Span())
Make a const value with certain data type.
Definition: op.h:1012
PrimExpr CanonicalizeIndex(PrimExpr index, PrimExpr extent, PrimExpr stride)
Definition: transform.h:679
ffi::Array< PrimExpr > StridedSliceOutputShape(const ffi::Array< PrimExpr > &ishape, const ffi::Array< ffi::Optional< IntImm >> &begin, const ffi::Array< ffi::Optional< IntImm >> &end, const ffi::Array< IntImm > &strides, const ffi::Array< int64_t > &axes, const std::string &slice_mode)
Calculate the output shape of strided_slice, the entry point for Relax type relation.
Definition: transform.h:868
Tensor cast(const Tensor &x, PrimType type, std::string name, std::string tag)
Cast each element of x to the given type. If expr is scalar and type is a corresponding vector type,...
Definition: elemwise.h:287
An object that builds and maintains block scope and StmtSref mapping for Dependence analysis.
Definition: analyzer.h:40
PrimExpr max(PrimExpr a, PrimExpr b, Span span=Span())
take maximum of two values
PrimExpr if_then_else(PrimExpr cond, PrimExpr true_value, PrimExpr false_value, Span span=Span())
Conditional expression.
PrimExpr min(PrimExpr a, PrimExpr b, Span span=Span())
take minimum of two values
PrimExpr abs(PrimExpr x, Span span=Span())
Calculate absolute value of x.
TIR expressions.