This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-tirx.git
The following commit(s) were added to refs/heads/main by this push:
new 3b95be67 [REFACTOR] Expose expression patterns and organize analysis
APIs (#1)
3b95be67 is described below
commit 3b95be6782ff60ef547b3cd5bf052d9a313d5053
Author: Tianqi Chen <[email protected]>
AuthorDate: Tue Oct 20 15:25:29 2026 -0400
[REFACTOR] Expose expression patterns and organize analysis APIs (#1)
Make the existing pattern matcher and inline constant folding reusable
through public IR headers while preserving their matching and evaluation
behavior.
- Separate shared captures and pattern composition from primitive
expression patterns.
- Move linear-equation and clip-bound detection into TIRx analysis, and
consolidate bound deduction with integer sets.
- Expose symbolic infinity accessors backed by private singleton
storage, and update C++ and Python consumers to their owning APIs.
---
.github/workflows/main.yml | 10 -
CMakeLists.txt | 2 +-
docs/reference/python/sym.rst | 2 -
docs/reference/python/tirx.analysis.rst | 2 +
include/tvm/ir/pattern_match.h | 312 +++++++++++++++++++++
{src => include/tvm}/ir/prim/const_fold.h | 104 ++-----
include/tvm/ir/prim/op.h | 28 ++
{src/sym => include/tvm/ir/prim}/pattern_match.h | 306 ++------------------
include/tvm/runtime/base.h | 2 +-
include/tvm/sym/bound.h | 53 ----
include/tvm/sym/int_set.h | 18 ++
include/tvm/sym/pattern.h | 55 ----
include/tvm/tirx/analysis.h | 22 ++
pyproject.toml | 2 +-
python/tvm_tirx/libinfo.py | 2 +-
python/tvm_tirx/sym/__init__.py | 3 +-
python/tvm_tirx/sym/bound.py | 40 ---
python/tvm_tirx/sym/int_set.py | 21 ++
python/tvm_tirx/sym/pattern.py | 61 ----
python/tvm_tirx/tirx/analysis/analysis.py | 42 +++
src/backend/cuda/tile/exec_analysis.cc | 4 +-
src/backend/webgpu/codegen/codegen_webgpu.cc | 10 +-
src/codegen/c/codegen_c.cc | 10 +-
src/codegen/llvm/codegen_llvm.cc | 8 +-
src/ir/prim/int_operator.h | 4 +-
src/ir/prim/math.cc | 2 +-
src/ir/prim/op.cc | 60 ++--
src/ir/prim/op_utils.h | 4 +-
src/ir/prim/symbolic_limits.cc | 19 +-
src/sym/analyzer.cc | 3 +-
src/sym/bound_deducer.cc | 4 +-
src/sym/canonical_simplify.cc | 2 +-
src/sym/const_fold.h | 16 +-
src/sym/const_int_bound.cc | 2 +-
src/sym/constraint_extract.cc | 3 +-
src/sym/int_operator.h | 8 +-
src/sym/int_set.cc | 76 ++---
src/sym/interval_set.h | 12 +-
src/sym/iter_affine_map.cc | 4 +-
src/sym/known_comparison_analyzer.cc | 2 +-
src/sym/modular_set.cc | 3 +-
src/sym/rewrite_simplify.cc | 147 +++++-----
src/sym/rewrite_simplify.h | 2 +-
.../analysis/linear_analysis.cc} | 16 +-
src/tirx/ir/tensor.cc | 5 +-
src/tirx/op/math.cc | 2 +-
src/tirx/tile/lower.cc | 1 -
src/tirx/transform/lower_intrin.cc | 6 +-
src/tirx/transform/remove_no_op.cc | 3 +-
src/tirx/transform/renormalize_split_pattern.cc | 3 +-
tests/cpp/{sym => ir}/pattern_match_test.cc | 20 +-
tests/cpp/sym/domain_map_test.cc | 1 -
.../analysis}/test_detect_clip_bound.py | 18 +-
.../analysis}/test_detect_linear_equation.py | 28 +-
54 files changed, 757 insertions(+), 838 deletions(-)
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index d7bdcdc0..603cfcbe 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -66,7 +66,6 @@ jobs:
shell: bash -l {0}
run: |
set -euxo pipefail
- export TVM_FFI_VERSION="$(python -c 'from importlib.metadata import
version; print(version("apache-tvm-ffi"))')"
pip install psutil cloudpickle ml_dtypes numpy packaging scipy
typing_extensions
# --no-deps: this package requires apache-tvm-ffi>=0.1.14.post1, and
the source-built core
# versions as 0.1.dev1+g<sha> from the shallow checkout, which is <
0.1.0 under PEP 440.
@@ -74,15 +73,6 @@ jobs:
pip install --no-deps "apache-tvm-ffi-orcjit>=0.1.2"
# Keep the source-matched tvm-ffi installed by the setup steps.
pip install --no-deps dist/*.whl
- python - <<'PY'
- import os
- from importlib.metadata import requires, version
-
- assert version("apache-tvm-ffi") == os.environ["TVM_FFI_VERSION"]
- assert version("apache-tvm-tirx") == "0.1.0a1"
- assert "apache-tvm-ffi>=0.1.15.post0" in requires("apache-tvm-tirx")
- assert "apache-tvm-ffi-orcjit>=0.1.2" in requires("apache-tvm-tirx")
- PY
- name: Test
shell: bash -l {0}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 43746a9b..6e81ddcd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,7 +32,7 @@ endfunction()
# ######### Common options ##########
-set(TVM_TIRX_VERSION "0.1.0a1")
+set(TVM_TIRX_VERSION "0.1.0a2")
if(PROJECT_IS_TOP_LEVEL)
tvm_tirx_option(TVM_TIRX_BUILD_TESTS BOOL OFF "Build C++ tests")
tvm_tirx_option(TVM_TIRX_BUILD_PYTHON_MODULE BOOL OFF "Build the Python
package with scikit-build-core")
diff --git a/docs/reference/python/sym.rst b/docs/reference/python/sym.rst
index 0f35e9df..703371cd 100644
--- a/docs/reference/python/sym.rst
+++ b/docs/reference/python/sym.rst
@@ -52,8 +52,6 @@ Functions
estimate_region_upper_bound
allow_uint_as_index
deduce_bound
- detect_linear_equation
- detect_clip_bound
detect_iter_map
iter_map_simplify
normalize_iter_map_to_expr
diff --git a/docs/reference/python/tirx.analysis.rst
b/docs/reference/python/tirx.analysis.rst
index fd428c8d..2ea762cb 100644
--- a/docs/reference/python/tirx.analysis.rst
+++ b/docs/reference/python/tirx.analysis.rst
@@ -32,3 +32,5 @@ Functions
verify_memory
undefined_vars
check_well_formed
+ detect_linear_equation
+ detect_clip_bound
diff --git a/include/tvm/ir/pattern_match.h b/include/tvm/ir/pattern_match.h
new file mode 100644
index 00000000..b903dc4d
--- /dev/null
+++ b/include/tvm/ir/pattern_match.h
@@ -0,0 +1,312 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file tvm/ir/pattern_match.h
+ * \brief Shared expression-template pattern and capture protocol.
+ *
+ * \code
+ * #include <tvm/ir/prim/pattern_match.h>
+ *
+ * void MatchMultiplyAdd(const tvm::PrimExpr& expr) {
+ * tvm::PVar<tvm::PrimExpr> a, b, c;
+ * if ((a * b + c).Match(expr)) {
+ * tvm::PrimExpr lhs = a.Eval();
+ * tvm::PrimExpr rhs = b.Eval();
+ * tvm::PrimExpr addend = c.Eval();
+ * }
+ * }
+ * \endcode
+ */
+#ifndef TVM_IR_PATTERN_MATCH_H_
+#define TVM_IR_PATTERN_MATCH_H_
+
+#include <tvm/ffi/cast.h>
+
+#include <optional>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+namespace tvm {
+/*!
+ * \brief Base class of all the patterns.
+ *
+ * There are two major member functions supported by each pattern.
+ * - Match: checks if value matches the pattern.
+ * - Eval: construct a new value based on matched values in PVar.
+ *
+ * We use curiously recurring template pattern to construct
+ * expression templates.
+ *
+ * \tparam Derived The type of the derived class.
+ */
+template <typename Derived>
+class Pattern {
+ public:
+ /*!
+ * \brief Nested storage type in the expression.
+ *
+ * Depending on the Derived class,
+ * Nested can be Derived (nest by value) or
+ * const Derived& (nest by reference).
+ *
+ * The trick of Nested typedef originates from Eigen.
+ *
+ * \note We use nest by value for intermediate expressions,
+ * and nest by reference for PVars.
+ */
+ using Nested = Derived;
+
+ /*!
+ * \brief Check if value matches the current pattern.
+ *
+ * This call also populates the PVars with matched value.
+ * The values in PVars are valid until the next call to Match.
+ *
+ * \param value The value to be matched against
+ *
+ * \return whether value matches the pattern.
+ */
+ template <typename NodeType>
+ inline bool Match(const NodeType& value) const {
+ return Match(value, []() { return true; });
+ }
+
+ /*!
+ * \brief Check if value matches the current pattern.
+ *
+ * This call also populates the PVars with matched value.
+ * The values in PVars are valid until the next call to Match.
+ *
+ * \param value The value to be matched against
+ *
+ * \param cond A callable that performs additional validation,
+ * returning true if the match passes. This will typically be a
+ * lambda function written in terms of the filled PVars.
+ *
+ * \return whether value matches the pattern.
+ */
+ template <typename NodeType, typename Condition>
+ bool Match(const NodeType& value, Condition cond) const {
+ derived().InitMatch_();
+ return derived().Match_(value) && cond();
+ }
+ /*! \return Derived instance of current class. */
+ const Derived& derived() const { return *static_cast<const Derived*>(this); }
+};
+
+/*!
+ * \brief Default deep equality checker
+ * \tparam T the comparison point.
+ */
+template <typename T>
+class PEqualChecker {
+ public:
+ bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; }
+};
+
+/*!
+ * \brief Pattern variable container.
+ *
+ * PVar is used as a "hole" in the pattern that can be matched.
+ *
+ * \tparam T the type of the hole.
+ *
+ * \note PVar is not thread safe.
+ * Do not use the same PVar in multiple threads.
+ */
+template <typename T>
+class PVar : public Pattern<PVar<T>> {
+ public:
+ // Store PVars by reference in the expression.
+ using Nested = const PVar<T>&;
+
+ void InitMatch_() const { value_.reset(); }
+
+ bool Match_(const T& value) const {
+ if (!value_) {
+ value_ = value;
+ return true;
+ } else {
+ return PEqualChecker<T>()(*value_, value);
+ }
+ }
+
+ template <typename NodeRefType, typename = typename std::enable_if<
+ !std::is_same<NodeRefType, T>::value &&
+ std::is_base_of<ffi::ObjectRef,
NodeRefType>::value &&
+ std::is_base_of<ffi::ObjectRef,
T>::value>::type>
+ bool Match_(const NodeRefType& value) const {
+ if (auto typed_value = value.template as<T>()) {
+ return Match_(*typed_value);
+ } else {
+ return false;
+ }
+ }
+
+ T Eval() const {
+ TVM_FFI_ICHECK(value_.has_value());
+ return *value_;
+ }
+
+ T EvalOr(const T& default_value) const { return
value_.value_or(default_value); }
+
+ protected:
+ /*! \brief The matched value */
+ mutable std::optional<T> value_;
+};
+
+/*!
+ * \brief Wrapper for pattern variable container with extra match logic.
+ *
+ * \tparam Derived the type of derived class.
+ * \tparam T the type of the hole.
+ */
+template <typename Derived, typename T>
+class PVarWithCheck : public Pattern<PVarWithCheck<Derived, T>> {
+ public:
+ // Store by reference in the expression.
+ using Nested = const PVarWithCheck<Derived, T>&;
+
+ void InitMatch_() const { pvar_.InitMatch_(); }
+
+ bool Match_(const T& value) const {
+ if (!static_cast<const Derived*>(this)->Match_(value)) return false;
+ return pvar_.Match_(value);
+ }
+
+ template <typename NodeRefType,
+ typename = typename std::enable_if<std::is_base_of<NodeRefType,
T>::value>::type>
+ bool Match_(const NodeRefType& value) const {
+ if (auto typed_value = value.template as<T>()) {
+ return Match_(*typed_value);
+ } else {
+ return false;
+ }
+ }
+
+ T Eval() const { return pvar_.Eval(); }
+
+ protected:
+ PVar<T> pvar_;
+};
+
+/*!
+ * \brief Constant Pattern variable container.
+ *
+ * \tparam T the type of the hole.
+ */
+template <typename T>
+class PConst : public Pattern<PConst<T>> {
+ public:
+ PConst(T value) // NOLINT(*)
+ : value_(value) {}
+
+ void InitMatch_() const {}
+
+ bool Match_(const T& value) const { return PEqualChecker<T>()(value_,
value); }
+
+ T Eval() const { return value_; }
+
+ private:
+ const T value_;
+};
+
+template <typename... TPattern>
+class PMatchesOneOf {
+ public:
+ explicit PMatchesOneOf(const TPattern&... patterns) : patterns_{patterns...}
{}
+
+ /*! \brief Check if value matches one of the patterns.
+ *
+ * This call also populates the PVars with matched value based on
+ * the first successful match. The values in PVars are valid until
+ * the next call to Match.
+ *
+ * \param value The value to be matched against.
+ *
+ * \return Whether value matches the pattern.
+ */
+ template <typename NodeType>
+ inline bool Match(const NodeType& value) const {
+ return Match(value, []() { return true; });
+ }
+
+ /*! \brief Check if value matches one of the patterns.
+ *
+ * This call also populates the PVars with matched value based on
+ * the first successful match. The values in PVars are valid until
+ * the next call to Match.
+ *
+ * \param value The value to be matched against.
+ *
+ * \param cond A callable that performs additional validation,
+ * returning true if the match passes. This will typically be a
+ * lambda function written in terms of the filled PVars. This will
+ * be called once for each successful pattern match. If `cond()`
+ * returns false, the next match will be attempted.
+ *
+ * \return Whether value matches the pattern.
+ */
+ template <typename NodeType, typename Condition>
+ inline bool Match(const NodeType& value, Condition cond) const {
+ return MatchImpl(value, cond,
std::make_index_sequence<sizeof...(TPattern)>());
+ }
+
+ private:
+ template <typename NodeType, typename Condition>
+ inline bool MatchImpl(const NodeType& value, Condition cond,
std::index_sequence<>) const {
+ return false;
+ }
+
+ template <typename NodeType, typename Condition, size_t FirstIndex,
size_t... RemainingIndices>
+ inline bool MatchImpl(const NodeType& value, Condition cond,
+ std::index_sequence<FirstIndex, RemainingIndices...>)
const {
+ return std::get<FirstIndex>(patterns_).Match(value, cond) ||
+ MatchImpl(value, cond, std::index_sequence<RemainingIndices...>());
+ }
+
+ // Hold the patterns by const&. This follows the same usage as both
+ // the `PVar`, which occurs as `const PVar<T>&` when it appears
+ // inside other patterns. Because the `PVar<T>::value_` field is
+ // mutable, it can still be updated through these const references.
+ // So long as the call to `Match()` occurs within the same
+ // expression as created the patterns, this avoids accidental copies
+ // without creating dangling references. This may be improved in
+ // the future by use of `constexpr` constructors/operators, allowing
+ // more typical value semantics.
+ std::tuple<const TPattern&...> patterns_;
+};
+
+/* \brief Return a proxy object that returns true after the first match
+ *
+ * In the RewriteSimplifier, there are often several expressions that
+ * simplify to the same resulting expression. This utility allows
+ * them to be specified as a single rule, reducing duplication of the
+ * result/condition of a rewrite.
+ */
+template <typename... TPattern>
+inline std::enable_if_t<(std::is_base_of_v<Pattern<TPattern>, TPattern> && ...
&& true),
+ PMatchesOneOf<TPattern...>>
+MatchesOneOf(const TPattern&... patterns) {
+ return PMatchesOneOf<TPattern...>(patterns...);
+}
+} // namespace tvm
+#endif // TVM_IR_PATTERN_MATCH_H_
diff --git a/src/ir/prim/const_fold.h b/include/tvm/ir/prim/const_fold.h
similarity index 81%
rename from src/ir/prim/const_fold.h
rename to include/tvm/ir/prim/const_fold.h
index 0a0f611e..8fcb7c17 100644
--- a/src/ir/prim/const_fold.h
+++ b/include/tvm/ir/prim/const_fold.h
@@ -18,7 +18,7 @@
*/
/*!
- * \file const_fold.h
+ * \file tvm/ir/prim/const_fold.h
* \brief Centralized location for constant folding.
*/
#ifndef TVM_IR_PRIM_CONST_FOLD_H_
@@ -32,11 +32,8 @@
#include <cmath>
#include <limits>
-#include "int_operator.h"
-
namespace tvm {
namespace prim {
-namespace detail {
/*!
* \brief Try to run binary compute with constant folding.
@@ -63,6 +60,8 @@ inline ffi::Optional<PrimExpr> TryConstFold(PrimExpr a,
PrimExpr b);
template <typename Op>
inline ffi::Optional<PrimExpr> TryConstFold(PrimExpr a);
+namespace details {
+
/*!
* \brief Check whether type is used to represent index.
*
@@ -128,6 +127,8 @@ inline double GetFoldResultDoubleRepr(float x) {
return res;
}
+} // namespace details
+
#define TVM_PRIM_CONST_PROPAGATION(BODY) \
using tvm::FloatImmNode; \
const IntImmNode* pa = a.as<IntImmNode>(); \
@@ -136,11 +137,11 @@ inline double GetFoldResultDoubleRepr(float x) {
const FloatImmNode* fb = b.as<FloatImmNode>(); \
BODY;
-#define TVM_PRIM_INDEX_CONST_PROPAGATION(BODY)
\
- const IntImmNode* pa = a.as<IntImmNode>();
\
- const IntImmNode* pb = b.as<IntImmNode>();
\
- if (::tvm::prim::detail::IsIndexTypedExpr(a) &&
::tvm::prim::detail::IsIndexTypedExpr(b)) { \
- BODY;
\
+#define TVM_PRIM_INDEX_CONST_PROPAGATION(BODY)
\
+ const IntImmNode* pa = a.as<IntImmNode>();
\
+ const IntImmNode* pb = b.as<IntImmNode>();
\
+ if (::tvm::prim::details::IsIndexTypedExpr(a) &&
::tvm::prim::details::IsIndexTypedExpr(b)) { \
+ BODY;
\
}
// specialization of constant folders.
@@ -150,14 +151,14 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::Add>(PrimExpr a, PrimExpr b) {
PrimType result_ty = a.ty();
if (pa && pb) {
ffi::BigInt res = pa->value + pb->value;
- return IntImm(result_ty, GetFoldResult(res, result_ty));
+ return IntImm(result_ty, details::GetFoldResult(res, result_ty));
}
if (pa && pa->value == 0) return b;
if (pb && pb->value == 0) return a;
if (fa && fb) {
if (result_ty.bits() == 32) {
- return FloatImm(result_ty,
GetFoldResultDoubleRepr(static_cast<float>(fa->value) +
-
static_cast<float>(fb->value)));
+ return FloatImm(result_ty,
details::GetFoldResultDoubleRepr(static_cast<float>(fa->value) +
+
static_cast<float>(fb->value)));
} else if (result_ty.bits() == 64) {
return FloatImm(result_ty, fa->value + fb->value);
}
@@ -180,13 +181,13 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::Sub>(PrimExpr a, PrimExpr b) {
PrimType result_ty = a.ty();
if (pa && pb) {
ffi::BigInt res = pa->value - pb->value;
- return IntImm(result_ty, GetFoldResult(res, result_ty));
+ return IntImm(result_ty, details::GetFoldResult(res, result_ty));
}
if (pb && pb->value == 0) return a;
if (fa && fb) {
if (result_ty.bits() == 32) {
- return FloatImm(result_ty,
GetFoldResultDoubleRepr(static_cast<float>(fa->value) -
-
static_cast<float>(fb->value)));
+ return FloatImm(result_ty,
details::GetFoldResultDoubleRepr(static_cast<float>(fa->value) -
+
static_cast<float>(fb->value)));
} else if (result_ty.bits() == 64) {
return FloatImm(result_ty, fa->value - fb->value);
}
@@ -202,7 +203,7 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::Mul>(PrimExpr a, PrimExpr b) {
PrimType result_ty = a.ty();
if (pa && pb) {
ffi::BigInt res = pa->value * pb->value;
- return IntImm(result_ty, GetFoldResult(res, result_ty));
+ return IntImm(result_ty, details::GetFoldResult(res, result_ty));
}
if (pa) {
if (pa->value == 1) return b;
@@ -214,8 +215,8 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::Mul>(PrimExpr a, PrimExpr b) {
}
if (fa && fb) {
if (result_ty.bits() == 32) {
- return FloatImm(result_ty,
GetFoldResultDoubleRepr(static_cast<float>(fa->value) *
-
static_cast<float>(fb->value)));
+ return FloatImm(result_ty,
details::GetFoldResultDoubleRepr(static_cast<float>(fa->value) *
+
static_cast<float>(fb->value)));
} else if (result_ty.bits() == 64) {
return FloatImm(result_ty, fa->value * fb->value);
}
@@ -241,7 +242,7 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::Div>(PrimExpr a, PrimExpr b) {
// NOTE: this will assumes truc div.
TVM_FFI_ICHECK_NE(pb->value, 0) << "Divide by zero";
ffi::BigInt res = pa->value / pb->value;
- return IntImm(result_ty, GetFoldResult(res, result_ty));
+ return IntImm(result_ty, details::GetFoldResult(res, result_ty));
}
if (pa) {
if (pa->value == 0) return a;
@@ -253,8 +254,8 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::Div>(PrimExpr a, PrimExpr b) {
if (fa && fb) {
TVM_FFI_ICHECK_NE(fb->value, 0) << "Divide by zero";
if (result_ty.bits() == 32) {
- return FloatImm(result_ty,
GetFoldResultDoubleRepr(static_cast<float>(fa->value) /
-
static_cast<float>(fb->value)));
+ return FloatImm(result_ty,
details::GetFoldResultDoubleRepr(static_cast<float>(fa->value) /
+
static_cast<float>(fb->value)));
} else if (result_ty.bits() == 64) {
return FloatImm(result_ty, fa->value / fb->value);
}
@@ -275,7 +276,7 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::Mod>(PrimExpr a, PrimExpr b) {
if (pa && pb) {
TVM_FFI_ICHECK_NE(pb->value, 0) << "Divide by zero";
ffi::BigInt res = pa->value % pb->value;
- return IntImm(result_ty, GetFoldResult(res, result_ty));
+ return IntImm(result_ty, details::GetFoldResult(res, result_ty));
}
if (pa) {
if (pa->value == 0) return a;
@@ -288,7 +289,7 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::Mod>(PrimExpr a, PrimExpr b) {
// Fold wide literals without enabling symbolic index rewrites for their
type.
if (pa && pb && a.ty().bits() >= 64) {
TVM_FFI_ICHECK_NE(pb->value, 0) << "Divide by zero";
- return IntImm(a.ty(), GetFoldResult(pa->value % pb->value, a.ty()));
+ return IntImm(a.ty(), details::GetFoldResult(pa->value % pb->value,
a.ty()));
}
return std::nullopt;
}
@@ -300,7 +301,7 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::FloorDiv>(PrimExpr a, PrimExpr
if (pa && pb) {
TVM_FFI_ICHECK_NE(pb->value, 0) << "Divide by zero";
ffi::BigInt res = ffi::floordiv(pa->value, pb->value);
- return IntImm(result_ty, GetFoldResult(res, result_ty));
+ return IntImm(result_ty, details::GetFoldResult(res, result_ty));
}
if (pa) {
if (pa->value == 0) return a;
@@ -311,9 +312,9 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::FloorDiv>(PrimExpr a, PrimExpr
}
if (fa && fb && fb->value != 0) {
if (result_ty.bits() == 32) {
- return FloatImm(result_ty,
-
GetFoldResultDoubleRepr(std::floor(static_cast<float>(fa->value) /
-
static_cast<float>(fb->value))));
+ return FloatImm(
+ result_ty,
details::GetFoldResultDoubleRepr(std::floor(static_cast<float>(fa->value) /
+
static_cast<float>(fb->value))));
} else if (result_ty.bits() == 64) {
return FloatImm(result_ty, std::floor(fa->value / fb->value));
} else {
@@ -336,7 +337,7 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::FloorMod>(PrimExpr a, PrimExpr
if (pa && pb) {
TVM_FFI_ICHECK_NE(pb->value, 0) << "Divide by zero";
ffi::BigInt res = ffi::floormod(pa->value, pb->value);
- return IntImm(result_ty, GetFoldResult(res, result_ty));
+ return IntImm(result_ty, details::GetFoldResult(res, result_ty));
}
if (pa) {
if (pa->value == 0) return a;
@@ -349,7 +350,7 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::FloorMod>(PrimExpr a, PrimExpr
// Fold wide literals without enabling symbolic index rewrites for their
type.
if (pa && pb && (a.ty().bits() >= 64 ||
a.ty().MatchesCode(DLDataTypeCode::kDLUInt))) {
TVM_FFI_ICHECK_NE(pb->value, 0) << "Divide by zero";
- return IntImm(a.ty(), GetFoldResult(ffi::floormod(pa->value, pb->value),
a.ty()));
+ return IntImm(a.ty(), details::GetFoldResult(ffi::floormod(pa->value,
pb->value), a.ty()));
}
return std::nullopt;
}
@@ -461,51 +462,6 @@ inline ffi::Optional<PrimExpr>
TryConstFold<prim::Not>(PrimExpr a) {
return std::nullopt;
}
-/*! \brief Shared symbolic value limits used by primitive folding and integer
analysis. */
-struct SymbolicLimits {
- /*! \brief positive infinity */
- static PrimExpr pos_inf_;
- /*! \brief negative infinity */
- static PrimExpr neg_inf_;
-};
-
-/*!
- * \brief Opaque expression representing positive infinity.
- *
- * It can only be used as parameter of by min/max
- * for integer analysis and cannot be used in normal expressions.
- *
- * \return positive infinity.
- */
-inline PrimExpr pos_inf() { return SymbolicLimits::pos_inf_; }
-
-/*!
- * \brief Check if value is positive infinity.
- * \param value The value to be checked.
- *
- * \return The check result.
- */
-inline bool is_pos_inf(const PrimExpr& value) { return
value.same_as(SymbolicLimits::pos_inf_); }
-
-/*!
- * \brief Opaque expression representing negative infinity.
- *
- * It can only be used as parameter of by min/max
- * for integer analysis and cannot be used in normal expressions.
- *
- * \return negative infinity.
- */
-inline PrimExpr neg_inf() { return SymbolicLimits::neg_inf_; }
-
-/*!
- * \brief Check if value is negative infinity.
- * \param value The value to be checked.
- *
- * \return The check result.
- */
-inline bool is_neg_inf(const PrimExpr& value) { return
value.same_as(SymbolicLimits::neg_inf_); }
-
-} // namespace detail
} // namespace prim
} // namespace tvm
#endif // TVM_IR_PRIM_CONST_FOLD_H_
diff --git a/include/tvm/ir/prim/op.h b/include/tvm/ir/prim/op.h
index f1eca89c..ff8563f7 100644
--- a/include/tvm/ir/prim/op.h
+++ b/include/tvm/ir/prim/op.h
@@ -265,6 +265,34 @@ inline PrimExpr operator*=(PrimExpr& a, PrimExpr b) {
namespace prim {
+/*!
+ * \brief Symbolic positive infinity for unbounded integer intervals.
+ * \note This sentinel is not IEEE infinity and cannot be used in normal
expressions.
+ * \return The positive infinity sentinel with stable identity and lifetime.
+ */
+TVM_TIRX_DLL const PrimExpr& pos_inf();
+
+/*!
+ * \brief Symbolic negative infinity for unbounded integer intervals.
+ * \note This sentinel is not IEEE infinity and cannot be used in normal
expressions.
+ * \return The negative infinity sentinel with stable identity and lifetime.
+ */
+TVM_TIRX_DLL const PrimExpr& neg_inf();
+
+/*!
+ * \brief Check whether a value is the symbolic positive infinity sentinel.
+ * \param value The value to check.
+ * \return Whether the value has the sentinel's identity.
+ */
+TVM_TIRX_DLL bool is_pos_inf(const PrimExpr& value);
+
+/*!
+ * \brief Check whether a value is the symbolic negative infinity sentinel.
+ * \param value The value to check.
+ * \return Whether the value has the sentinel's identity.
+ */
+TVM_TIRX_DLL bool is_neg_inf(const PrimExpr& value);
+
/*!
* \brief Get the target's vscale value. It will be lowered to llvm.vscale
intrinsic
* (https://llvm.org/docs/LangRef.html#llvm-vscale-intrinsic)
diff --git a/src/sym/pattern_match.h b/include/tvm/ir/prim/pattern_match.h
similarity index 69%
rename from src/sym/pattern_match.h
rename to include/tvm/ir/prim/pattern_match.h
index 4457461f..62506abb 100644
--- a/src/sym/pattern_match.h
+++ b/include/tvm/ir/prim/pattern_match.h
@@ -18,9 +18,9 @@
*/
/*!
- * \file tvm/arithmetic/pattern_match.h
+ * \file tvm/ir/prim/pattern_match.h
*
- * \brief Internal tool for expression-template based pattern matching.
+ * \brief Public tool for expression-template based pattern matching.
*
* It helps to simplify pattern matching and rewrites.
* All the patterns are generated via expression template during compile time,
@@ -31,7 +31,7 @@
* \code
*
* // max(x + z, y + z) => max(x, y) + z
- * sym::PVar<Expr> x, y, z;
+ * tvm::PVar<PrimExpr> x, y, z;
*
* // The following code tries to match the declared pattern.
* // Match will fill the result of match into PVar if successful.
@@ -44,9 +44,9 @@
* return (max(x, y) + z).Eval();
* }
*
- * tvm::Var tx, ty;
- * sym::PVar<IntImm> c;
- * sym::PVar<Var> v;
+ * tvm::PrimVar tx("tx"), ty("ty");
+ * tvm::PVar<IntImm> c;
+ * tvm::PVar<Var> v;
* // We can match integer and Var, both of which are
* // special case container of Expr
* TVM_FFI_ICHECK((v * c).Match(tx * 3));
@@ -62,97 +62,18 @@
* Please be aware that the filled value in a PVar
* can be overriden in the next call to Match.
*/
-#ifndef TVM_SYM_PATTERN_MATCH_H_
-#define TVM_SYM_PATTERN_MATCH_H_
+#ifndef TVM_IR_PRIM_PATTERN_MATCH_H_
+#define TVM_IR_PRIM_PATTERN_MATCH_H_
-#include <tvm/ffi/cast.h>
+#include <tvm/ir/pattern_match.h>
+#include <tvm/ir/prim/const_fold.h>
#include <tvm/ir/prim/expr.h>
#include <tvm/ir/prim/op.h>
#include <cmath>
#include <tuple>
-#include "const_fold.h"
-
namespace tvm {
-namespace sym {
-/*!
- * \brief Base class of all the patterns.
- *
- * There are two major member functions supported by each pattern.
- * - Match: checks if value matches the pattern.
- * - Eval: construct a new value based on matched values in PVar.
- *
- * We use curiously recurring template pattern to construct
- * expression templates.
- *
- * \tparam Derived The type of the derived class.
- */
-template <typename Derived>
-class Pattern {
- public:
- /*!
- * \brief Nested storage type in the expression.
- *
- * Depending on the Derived class,
- * Nested can be Derived (nest by value) or
- * const Derived& (nest by reference).
- *
- * The trick of Nested typedef originates from Eigen.
- *
- * \note We use nest by value for intermediate expressions,
- * and nest by reference for PVars.
- */
- using Nested = Derived;
-
- /*!
- * \brief Check if value matches the current pattern.
- *
- * This call also populates the PVars with matched value.
- * The values in PVars are valid until the next call to Match.
- *
- * \param value The value to be matched against
- *
- * \return whether value matches the pattern.
- */
- template <typename NodeType>
- inline bool Match(const NodeType& value) const {
- return Match(value, []() { return true; });
- }
-
- /*!
- * \brief Check if value matches the current pattern.
- *
- * This call also populates the PVars with matched value.
- * The values in PVars are valid until the next call to Match.
- *
- * \param value The value to be matched against
- *
- * \param cond A callable that performs additional validation,
- * returning true if the match passes. This will typically be a
- * lambda function written in terms of the filled PVars.
- *
- * \return whether value matches the pattern.
- */
- template <typename NodeType, typename Condition>
- bool Match(const NodeType& value, Condition cond) const {
- derived().InitMatch_();
- return derived().Match_(value) && cond();
- }
- /*! \return Derived instance of current class. */
- const Derived& derived() const { return *static_cast<const Derived*>(this); }
-};
-
-/*!
- * \brief Default deep equality checker
- * \tparam T the comparison point.
- */
-template <typename T>
-class PEqualChecker {
- public:
- bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; }
-};
-
template <>
class PEqualChecker<PrimExpr> {
public:
@@ -182,92 +103,6 @@ class PEqualChecker<Var> {
bool operator()(const Var& lhs, const Var& rhs) const { return
lhs.same_as(rhs); }
};
-/*!
- * \brief Pattern variable container.
- *
- * PVar is used as a "hole" in the pattern that can be matched.
- *
- * \tparam T the type of the hole.
- *
- * \note PVar is not thread safe.
- * Do not use the same PVar in multiple threads.
- */
-template <typename T>
-class PVar : public Pattern<PVar<T>> {
- public:
- // Store PVars by reference in the expression.
- using Nested = const PVar<T>&;
-
- void InitMatch_() const { value_.reset(); }
-
- bool Match_(const T& value) const {
- if (!value_) {
- value_ = value;
- return true;
- } else {
- return PEqualChecker<T>()(*value_, value);
- }
- }
-
- template <typename NodeRefType, typename = typename std::enable_if<
- !std::is_same<NodeRefType, T>::value &&
- std::is_base_of<ffi::ObjectRef,
NodeRefType>::value &&
- std::is_base_of<ffi::ObjectRef,
T>::value>::type>
- bool Match_(const NodeRefType& value) const {
- if (auto typed_value = value.template as<T>()) {
- return Match_(*typed_value);
- } else {
- return false;
- }
- }
-
- T Eval() const {
- TVM_FFI_ICHECK(value_.has_value());
- return *value_;
- }
-
- T EvalOr(const T& default_value) const { return
value_.value_or(default_value); }
-
- protected:
- /*! \brief The matched value */
- mutable std::optional<T> value_;
-};
-
-/*!
- * \brief Wrapper for pattern variable container with extra match logic.
- *
- * \tparam Derived the type of derived class.
- * \tparam T the type of the hole.
- */
-template <typename Derived, typename T>
-class PVarWithCheck : public sym::Pattern<PVarWithCheck<Derived, T>> {
- public:
- // Store by reference in the expression.
- using Nested = const PVarWithCheck<Derived, T>&;
-
- void InitMatch_() const { pvar_.InitMatch_(); }
-
- bool Match_(const T& value) const {
- if (!static_cast<const Derived*>(this)->Match_(value)) return false;
- return pvar_.Match_(value);
- }
-
- template <typename NodeRefType,
- typename = typename std::enable_if<std::is_base_of<NodeRefType,
T>::value>::type>
- bool Match_(const NodeRefType& value) const {
- if (auto typed_value = value.template as<T>()) {
- return Match_(*typed_value);
- } else {
- return false;
- }
- }
-
- T Eval() const { return pvar_.Eval(); }
-
- protected:
- sym::PVar<T> pvar_;
-};
-
/*!
* \brief Pattern variable container with expr type check.
*
@@ -300,27 +135,6 @@ class PVecDataType : public PVarWithCheck<PVecDataType,
DLDataType> {
DLDataType elem_dtype_;
};
-/*!
- * \brief Constant Pattern variable container.
- *
- * \tparam T the type of the hole.
- */
-template <typename T>
-class PConst : public Pattern<PConst<T>> {
- public:
- PConst(T value) // NOLINT(*)
- : value_(value) {}
-
- void InitMatch_() const {}
-
- bool Match_(const T& value) const { return PEqualChecker<T>()(value_,
value); }
-
- T Eval() const { return value_; }
-
- private:
- const T value_;
-};
-
/*!
* \brief Pattern binary expression.
* \tparam OpType The AST noderef type.
@@ -353,7 +167,7 @@ class PBinaryExpr : public Pattern<PBinaryExpr<OpType, TA,
TB, kFoldConstants>>
PrimExpr lhs = a_.Eval();
PrimExpr rhs = b_.Eval();
if constexpr (kFoldConstants) {
- if (auto ret = TryConstFold<OpType>(lhs, rhs)) return ret.value();
+ if (auto ret = prim::TryConstFold<OpType>(lhs, rhs)) return ret.value();
}
return OpType(lhs, rhs);
}
@@ -734,7 +548,7 @@ inline PBroadcastExpr<TA, TLanes> broadcast(const
Pattern<TA>& value,
}
// internal namespace
-namespace detail {
+namespace details {
// implementation details for CallExpr
template <bool stop, std::size_t I, typename F>
struct tuple_for_each_dispatcher {
@@ -783,7 +597,7 @@ struct PCallExprEvalArgsFunctor {
args_.push_back(pattern.Eval());
}
};
-} // namespace detail
+} // namespace details
/*!
* \brief Pattern CallExpr expression.
@@ -798,16 +612,16 @@ class PCallExpr : public Pattern<PCallExpr<Op, TArgs...>>
{
explicit PCallExpr(const TArgs&... args) : args_(args...) {}
void InitMatch_() const {
- detail::PCallExprInitMatchFunctor finit;
- detail::tuple_for_each(finit, args_);
+ details::PCallExprInitMatchFunctor finit;
+ details::tuple_for_each(finit, args_);
}
bool Match_(const ffi::ObjectRef& node) const {
if (const CallNode* ptr = node.as<CallNode>()) {
if (ptr->args.size() != sizeof...(TArgs)) return false;
if (!ptr->op.same_as(Op::GetOp())) return false;
- detail::PCallExprMatchFunctor fmatch(ptr);
- detail::tuple_for_each(fmatch, args_);
+ details::PCallExprMatchFunctor fmatch(ptr);
+ details::tuple_for_each(fmatch, args_);
return fmatch.matched_;
} else {
return false;
@@ -815,8 +629,8 @@ class PCallExpr : public Pattern<PCallExpr<Op, TArgs...>> {
}
PrimExpr Eval() const {
- detail::PCallExprEvalArgsFunctor feval_args;
- detail::tuple_for_each(feval_args, args_);
+ details::PCallExprEvalArgsFunctor feval_args;
+ details::tuple_for_each(feval_args, args_);
return Op::Eval(feval_args.args_);
}
@@ -853,85 +667,5 @@ inline PCallExpr<PIfThenElseOp, TCond, TA, TB>
if_then_else(const Pattern<TCond>
false_value.derived());
}
-template <typename... TPattern>
-class PMatchesOneOf {
- public:
- explicit PMatchesOneOf(const TPattern&... patterns) : patterns_{patterns...}
{}
-
- /*! \brief Check if value matches one of the patterns.
- *
- * This call also populates the PVars with matched value based on
- * the first successful match. The values in PVars are valid until
- * the next call to Match.
- *
- * \param value The value to be matched against.
- *
- * \return Whether value matches the pattern.
- */
- template <typename NodeType>
- inline bool Match(const NodeType& value) const {
- return Match(value, []() { return true; });
- }
-
- /*! \brief Check if value matches one of the patterns.
- *
- * This call also populates the PVars with matched value based on
- * the first successful match. The values in PVars are valid until
- * the next call to Match.
- *
- * \param value The value to be matched against.
- *
- * \param cond A callable that performs additional validation,
- * returning true if the match passes. This will typically be a
- * lambda function written in terms of the filled PVars. This will
- * be called once for each successful pattern match. If `cond()`
- * returns false, the next match will be attempted.
- *
- * \return Whether value matches the pattern.
- */
- template <typename NodeType, typename Condition>
- inline bool Match(const NodeType& value, Condition cond) const {
- return MatchImpl(value, cond,
std::make_index_sequence<sizeof...(TPattern)>());
- }
-
- private:
- template <typename NodeType, typename Condition>
- inline bool MatchImpl(const NodeType& value, Condition cond,
std::index_sequence<>) const {
- return false;
- }
-
- template <typename NodeType, typename Condition, size_t FirstIndex,
size_t... RemainingIndices>
- inline bool MatchImpl(const NodeType& value, Condition cond,
- std::index_sequence<FirstIndex, RemainingIndices...>)
const {
- return std::get<FirstIndex>(patterns_).Match(value, cond) ||
- MatchImpl(value, cond, std::index_sequence<RemainingIndices...>());
- }
-
- // Hold the patterns by const&. This follows the same usage as both
- // the `PVar`, which occurs as `const PVar<T>&` when it appears
- // inside other patterns. Because the `PVar<T>::value_` field is
- // mutable, it can still be updated through these const references.
- // So long as the call to `Match()` occurs within the same
- // expression as created the patterns, this avoids accidental copies
- // without creating dangling references. This may be improved in
- // the future by use of `constexpr` constructors/operators, allowing
- // more typical value semantics.
- std::tuple<const TPattern&...> patterns_;
-};
-
-/* \brief Return a proxy object that returns true after the first match
- *
- * In the RewriteSimplifier, there are often several expressions that
- * simplify to the same resulting expression. This utility allows
- * them to be specified as a single rule, reducing duplication of the
- * result/condition of a rewrite.
- */
-template <typename... TPattern>
-inline std::enable_if_t<(std::is_base_of_v<Pattern<TPattern>, TPattern> && ...
&& true),
- PMatchesOneOf<TPattern...>>
-matches_one_of(const TPattern&... patterns) {
- return PMatchesOneOf<TPattern...>(patterns...);
-}
-} // namespace sym
} // namespace tvm
-#endif // TVM_SYM_PATTERN_MATCH_H_
+#endif // TVM_IR_PRIM_PATTERN_MATCH_H_
diff --git a/include/tvm/runtime/base.h b/include/tvm/runtime/base.h
index 95d75e28..4e79fff6 100644
--- a/include/tvm/runtime/base.h
+++ b/include/tvm/runtime/base.h
@@ -32,7 +32,7 @@
// passes the setuptools_scm-resolved version through CMake). The literal
below is the
// fallback for a bare build with no override.
#ifndef TVM_TIRX_VERSION
-#define TVM_TIRX_VERSION "0.1.0a1"
+#define TVM_TIRX_VERSION "0.1.0a2"
#endif
// Core runtime visibility is independent of TIRx compiler visibility.
diff --git a/include/tvm/sym/bound.h b/include/tvm/sym/bound.h
deleted file mode 100644
index 5bee6ddd..00000000
--- a/include/tvm/sym/bound.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-/*!
- * \file tvm/sym/bound.h
- * \brief Bound deducers.
- */
-#ifndef TVM_SYM_BOUND_H_
-#define TVM_SYM_BOUND_H_
-
-#include <tvm/ir/expr.h>
-#include <tvm/ir/prim/expr.h>
-#include <tvm/sym/int_set.h>
-
-namespace tvm {
-namespace sym {
-
-/*!
- * \brief Deduce the bound of the target variable in an expression,
- * given the domain of each variable. Return IntSet::Nothing() to
- * represent failure.
- *
- * \note The returned set may be smaller than set that
- * contains all possible values of v that satisfies the bound.
- *
- * \param v The target variable to be deduced.
- * \param cond The conditional expression.
- * \param hint_map The domain of variable, used to help deduce.
- * \param relax_map The domain of each variable, used to relax the domain,
- * The deduce bound must imply e for all value in relax_map
- * \return An integer set that always satisfies the condition.
- */
-TVM_TIRX_DLL IntSet DeduceBound(PrimExpr v, PrimExpr cond, const ffi::Map<Var,
IntSet>& hint_map,
- const ffi::Map<Var, IntSet>& relax_map);
-
-} // namespace sym
-} // namespace tvm
-#endif // TVM_SYM_BOUND_H_
diff --git a/include/tvm/sym/int_set.h b/include/tvm/sym/int_set.h
index c71307c4..c0fd55bf 100644
--- a/include/tvm/sym/int_set.h
+++ b/include/tvm/sym/int_set.h
@@ -303,6 +303,24 @@ TVM_TIRX_DLL ffi::Array<IntSet>
EstimateRegionUpperBound(const ffi::Array<Range>
const PrimExpr&
predicate,
const sym::Analyzer&
analyzer);
+/*!
+ * \brief Deduce the bound of the target variable in an expression,
+ * given the domain of each variable. Return IntSet::Nothing() to
+ * represent failure.
+ *
+ * \note The returned set may be smaller than set that
+ * contains all possible values of v that satisfies the bound.
+ *
+ * \param v The target variable to be deduced.
+ * \param cond The conditional expression.
+ * \param hint_map The domain of variable, used to help deduce.
+ * \param relax_map The domain of each variable, used to relax the domain,
+ * The deduce bound must imply e for all value in relax_map
+ * \return An integer set that always satisfies the condition.
+ */
+TVM_TIRX_DLL IntSet DeduceBound(PrimExpr v, PrimExpr cond, const ffi::Map<Var,
IntSet>& hint_map,
+ const ffi::Map<Var, IntSet>& relax_map);
+
} // namespace sym
} // namespace tvm
#endif // TVM_SYM_INT_SET_H_
diff --git a/include/tvm/sym/pattern.h b/include/tvm/sym/pattern.h
deleted file mode 100644
index 42fc25c8..00000000
--- a/include/tvm/sym/pattern.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-
-/*!
- * \file tvm/sym/pattern.h
- * \brief Expression pattern detectors.
- */
-#ifndef TVM_SYM_PATTERN_H_
-#define TVM_SYM_PATTERN_H_
-
-#include <tvm/ir/expr.h>
-
-namespace tvm {
-namespace sym {
-/*!
- * \brief Detect if e can be rewritten as e = sum_{i=0}^{n-1} var[i] *
coeff[i] + coeff[n]
- * Where coeff[i] and base are invariant of var[j] for all i and j.
- *
- * \param e The expression to be detected.
- * \param vars List of variables to be used in detection.
- * \return [coeff[i]] if it is possible, empty array if it is not.
- */
-TVM_TIRX_DLL ffi::Array<PrimExpr> DetectLinearEquation(const PrimExpr& e,
- const
ffi::Array<PrimVar>& vars);
-
-/*!
- * \brief Detect if expression corresponds to clip bound of the vars
- *
- * \param e The expression to be detected.
- * \param vars List of variables to be used in detection.
- * \return concat([min_value[i], max_value[i]]), None is returned if there is
no min or max value
- * return empty if the e does not match the pattern.
- */
-ffi::Array<ffi::Optional<PrimExpr>> DetectClipBound(const PrimExpr& e,
- const ffi::Array<PrimVar>&
vars);
-
-} // namespace sym
-} // namespace tvm
-#endif // TVM_SYM_PATTERN_H_
diff --git a/include/tvm/tirx/analysis.h b/include/tvm/tirx/analysis.h
index fa19ccdc..2d19c902 100644
--- a/include/tvm/tirx/analysis.h
+++ b/include/tvm/tirx/analysis.h
@@ -38,6 +38,28 @@ namespace tvm {
namespace tirx {
+/*!
+ * \brief Detect if e can be rewritten as e = sum_{i=0}^{n-1} var[i] *
coeff[i] + coeff[n]
+ * Where coeff[i] and base are invariant of var[j] for all i and j.
+ *
+ * \param e The expression to be detected.
+ * \param vars List of variables to be used in detection.
+ * \return [coeff[i]] if it is possible, empty array if it is not.
+ */
+TVM_TIRX_DLL ffi::Array<PrimExpr> DetectLinearEquation(const PrimExpr& e,
+ const
ffi::Array<PrimVar>& vars);
+
+/*!
+ * \brief Detect if expression corresponds to clip bound of the vars
+ *
+ * \param e The expression to be detected.
+ * \param vars List of variables to be used in detection.
+ * \return concat([min_value[i], max_value[i]]), None is returned if there is
no min or max value
+ * return empty if the e does not match the pattern.
+ */
+TVM_TIRX_DLL ffi::Array<ffi::Optional<PrimExpr>> DetectClipBound(const
PrimExpr& e,
+ const
ffi::Array<PrimVar>& vars);
+
/*!
* \brief Verify if memory accesses are legal for a specific target device
type.
*
diff --git a/pyproject.toml b/pyproject.toml
index efc79d88..22254d49 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -17,7 +17,7 @@
[project]
name = "apache-tvm-tirx"
-version = "0.1.0a1"
+version = "0.1.0a2"
description = "TVM TIRx"
license = "Apache-2.0"
license-files = ["LICENSE"]
diff --git a/python/tvm_tirx/libinfo.py b/python/tvm_tirx/libinfo.py
index 8dad587a..cf72e4b4 100644
--- a/python/tvm_tirx/libinfo.py
+++ b/python/tvm_tirx/libinfo.py
@@ -94,7 +94,7 @@ def find_include_path() -> str:
raise RuntimeError("Cannot find TVM include path.")
-__version__ = "0.1.0a1"
+__version__ = "0.1.0a2"
_LIBRARY_NAMES = ("tvm_tirx_compiler", "tvm_runtime")
diff --git a/python/tvm_tirx/sym/__init__.py b/python/tvm_tirx/sym/__init__.py
index 59274c09..cf1ec6bb 100644
--- a/python/tvm_tirx/sym/__init__.py
+++ b/python/tvm_tirx/sym/__init__.py
@@ -20,6 +20,7 @@
from .int_set import (
IntSet,
IntervalSet,
+ deduce_bound,
estimate_region_lower_bound,
estimate_region_strict_bound,
estimate_region_upper_bound,
@@ -32,8 +33,6 @@ from .analyzer import (
CompareResult,
allow_uint_as_index,
)
-from .bound import deduce_bound
-from .pattern import detect_linear_equation, detect_clip_bound
from .iter_affine_map import IterMapExpr, IterMark, IterSplitExpr, IterSumExpr
from .iter_affine_map import (
detect_iter_map,
diff --git a/python/tvm_tirx/sym/bound.py b/python/tvm_tirx/sym/bound.py
deleted file mode 100644
index f000fa74..00000000
--- a/python/tvm_tirx/sym/bound.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# 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.
-"""Bound deduction."""
-
-from . import _ffi_api
-
-
-def deduce_bound(var, cond, hint_map, relax_map):
- """Deduce the bound of the target variable in the cond.
-
- Parameters
- ----------
- var : tvm_tirx.ir.Var
- The target variable to be deduced.
-
- cond : Expr
- The condition
-
- hint_map : Map[tvm_tirx.ir.Var, IntSet]
- Domain of variables used to help deduction.
-
- relax_map : Map[tvm_tirx.ir.Var, IntSet]
- The domain of the variables to be relaxed
- using the provided domain.
- """
- return _ffi_api.DeduceBound(var, cond, hint_map, relax_map)
diff --git a/python/tvm_tirx/sym/int_set.py b/python/tvm_tirx/sym/int_set.py
index 57b35449..fa96e852 100644
--- a/python/tvm_tirx/sym/int_set.py
+++ b/python/tvm_tirx/sym/int_set.py
@@ -201,3 +201,24 @@ def union_lower_bound(sets):
An N-dimensional integer set, the lower bound of the union
"""
return _ffi_api.UnionLowerBound(sets)
+
+
+def deduce_bound(var, cond, hint_map, relax_map):
+ """Deduce the bound of the target variable in the cond.
+
+ Parameters
+ ----------
+ var : tvm_tirx.ir.Var
+ The target variable to be deduced.
+
+ cond : Expr
+ The condition
+
+ hint_map : Map[tvm_tirx.ir.Var, IntSet]
+ Domain of variables used to help deduction.
+
+ relax_map : Map[tvm_tirx.ir.Var, IntSet]
+ The domain of the variables to be relaxed
+ using the provided domain.
+ """
+ return _ffi_api.DeduceBound(var, cond, hint_map, relax_map)
diff --git a/python/tvm_tirx/sym/pattern.py b/python/tvm_tirx/sym/pattern.py
deleted file mode 100644
index 5bec413c..00000000
--- a/python/tvm_tirx/sym/pattern.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# 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.
-"""Detect bounds, affine forms, and other patterns in symbolic expressions."""
-
-from . import _ffi_api
-
-
-def detect_linear_equation(expr, var_list):
- """Match `expr = sum_{i=0}^{n-1} var[i] * coeff[i] + coeff[n]`
-
- Where coeff[i] and base are invariant of var[j] for all i and j.
-
- Parameters
- ----------
- expr : Expr
- The expression to be matched.
-
- var_list : List[tvm_tirx.ir.Var]
- A list of variables.
-
- Returns
- -------
- coeff : List[Expr]
- A list of co-efficients if the match is successful.
- An empty list if the match failed.
- """
- return _ffi_api.DetectLinearEquation(expr, var_list)
-
-
-def detect_clip_bound(expr, var_list):
- """Detect if expression corresponds to clip bound of the vars
-
- Parameters
- ----------
- expr : Expr
- The expression to be matched.
-
- var_list : List[tvm_tirx.ir.Var]
- A list of variables.
-
- Returns
- -------
- coeff : List[Expr]
- `concat([min_value[i], max_value[i]] for i, v in enumerate(var_list))`
- An empty list if the match failed.
- """
- return _ffi_api.DetectClipBound(expr, var_list)
diff --git a/python/tvm_tirx/tirx/analysis/analysis.py
b/python/tvm_tirx/tirx/analysis/analysis.py
index d0c6d990..18f35f61 100644
--- a/python/tvm_tirx/tirx/analysis/analysis.py
+++ b/python/tvm_tirx/tirx/analysis/analysis.py
@@ -83,3 +83,45 @@ def check_well_formed(obj: Function | IRModule, assert_mode:
bool = True) -> boo
If the IR is invalid and assert_mode is True.
"""
return _ffi_api.CheckWellFormed(obj, assert_mode) # type: ignore #
pylint: disable=no-member
+
+
+def detect_linear_equation(expr, var_list):
+ """Match `expr = sum_{i=0}^{n-1} var[i] * coeff[i] + coeff[n]`
+
+ Where coeff[i] and base are invariant of var[j] for all i and j.
+
+ Parameters
+ ----------
+ expr : Expr
+ The expression to be matched.
+
+ var_list : List[tvm_tirx.ir.Var]
+ A list of variables.
+
+ Returns
+ -------
+ coeff : List[Expr]
+ A list of co-efficients if the match is successful.
+ An empty list if the match failed.
+ """
+ return _ffi_api.DetectLinearEquation(expr, var_list)
+
+
+def detect_clip_bound(expr, var_list):
+ """Detect if expression corresponds to clip bound of the vars
+
+ Parameters
+ ----------
+ expr : Expr
+ The expression to be matched.
+
+ var_list : List[tvm_tirx.ir.Var]
+ A list of variables.
+
+ Returns
+ -------
+ coeff : List[Expr]
+ `concat([min_value[i], max_value[i]] for i, v in enumerate(var_list))`
+ An empty list if the match failed.
+ """
+ return _ffi_api.DetectClipBound(expr, var_list)
diff --git a/src/backend/cuda/tile/exec_analysis.cc
b/src/backend/cuda/tile/exec_analysis.cc
index 66a3b100..d38e17af 100644
--- a/src/backend/cuda/tile/exec_analysis.cc
+++ b/src/backend/cuda/tile/exec_analysis.cc
@@ -25,8 +25,8 @@
#include <tvm/ir/prim/op.h>
#include <tvm/runtime/logging.h>
#include <tvm/sym/analyzer.h>
-#include <tvm/sym/pattern.h>
#include <tvm/target/target.h>
+#include <tvm/tirx/analysis.h>
#include <tvm/tirx/function.h>
#include <tvm/tirx/op/annotation.h>
#include <tvm/tirx/op/attr.h>
@@ -547,7 +547,7 @@ struct ExecAnalysis::Impl {
int64_t* base) {
PrimExpr simplified = analyzer_->Simplify(diff);
for (const auto& [var, candidate] : ScopeIdTargets()) {
- ffi::Array<PrimExpr> linear = sym::DetectLinearEquation(simplified,
{var});
+ ffi::Array<PrimExpr> linear = tirx::DetectLinearEquation(simplified,
{var});
if (linear.size() != 2) continue;
int64_t c = 0;
int64_t b = 0;
diff --git a/src/backend/webgpu/codegen/codegen_webgpu.cc
b/src/backend/webgpu/codegen/codegen_webgpu.cc
index c4d6f360..e52b305a 100644
--- a/src/backend/webgpu/codegen/codegen_webgpu.cc
+++ b/src/backend/webgpu/codegen/codegen_webgpu.cc
@@ -27,6 +27,7 @@
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ir/function.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/runtime/memory_scope.h>
#include <tvm/support/bytes_io.h>
#include <tvm/support/gpu_thread_tag.h>
@@ -49,7 +50,6 @@
#include "../../../codegen/build_common.h"
#include "../../../runtime/metadata.h"
-#include "../../../sym/pattern_match.h"
#include "webgpu_fallback_module.h"
namespace tvm {
@@ -657,8 +657,8 @@ void CodeGenWebGPU::Dispatch_(const TensorLoadNode* op,
std::ostream& os) { //
TVM_FFI_ICHECK_EQ(element_ty.lanes(), 1) << "Can only vector load scalar
array";
TVM_FFI_ICHECK(value_ty.WithLanes(1) == element_ty)
<< "WebGPU vector loading requires base type to match";
- sym::PVar<PrimExpr> base;
- if (sym::ramp(base, 1, value_ty.lanes()).Match(index)) {
+ tvm::PVar<PrimExpr> base;
+ if (tvm::ramp(base, 1, value_ty.lanes()).Match(index)) {
// vec3<f32>(buf[base + 0], buf[base + 1], buf[base + 2]);
std::string base_vid = SSAGetID(PrintExpr(base.Eval()),
base.Eval().ty());
PrintType(element_ty.WithLanes(value_ty.lanes()), os);
@@ -743,8 +743,8 @@ void CodeGenWebGPU::Dispatch_(const TensorStoreNode* op) {
TVM_FFI_ICHECK(value_ty.WithLanes(1) == element_ty)
<< "WebGPU vector stire requires base type to match";
std::string value_vid = PrintExpr(op->value);
- sym::PVar<PrimExpr> base;
- if (sym::ramp(base, 1, value_ty.lanes()).Match(index)) {
+ tvm::PVar<PrimExpr> base;
+ if (tvm::ramp(base, 1, value_ty.lanes()).Match(index)) {
// buf[base + 0] = value[0]
// buf[base + 1] = value[1]
std::string base_vid = SSAGetID(PrintExpr(base.Eval()),
base.Eval().ty());
diff --git a/src/codegen/c/codegen_c.cc b/src/codegen/c/codegen_c.cc
index 27843901..dbb603a4 100644
--- a/src/codegen/c/codegen_c.cc
+++ b/src/codegen/c/codegen_c.cc
@@ -26,6 +26,7 @@
#include <tvm/ffi/extra/structural_equal.h>
#include <tvm/ir/function.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/ir/unique_name_supply.h>
#include <tvm/runtime/memory_scope.h>
#include <tvm/sym/analyzer.h>
@@ -41,7 +42,6 @@
#include <iomanip>
#include <limits>
-#include "../../sym/pattern_match.h"
#include "codegen_params.h"
namespace tvm {
@@ -1016,8 +1016,8 @@ void CodeGenC::Dispatch_(const TensorLoadNode* op,
std::ostream& os) { // NOLIN
}
} else {
bool can_vector_load = false;
- sym::PVar<PrimExpr> base;
- if (sym::ramp(base, 1, value_ty.lanes()).Match(index)) {
+ tvm::PVar<PrimExpr> base;
+ if (tvm::ramp(base, 1, value_ty.lanes()).Match(index)) {
const prim::RampNode* ramp = index.as<prim::RampNode>();
TVM_FFI_ICHECK(ramp);
sym::ModularSet me = sym::Analyzer()->modular_set(ramp->base);
@@ -1082,9 +1082,9 @@ void CodeGenC::Dispatch_(const TensorStoreNode* op) {
this->PrintIndent();
stream << ref << " = " << value << ";\n";
} else {
- sym::PVar<PrimExpr> base;
+ tvm::PVar<PrimExpr> base;
- if (sym::ramp(base, 1, value_ty.lanes()).Match(index_expr) &&
+ if (tvm::ramp(base, 1, value_ty.lanes()).Match(index_expr) &&
value_ty.code() != DLDataTypeCode::kDLFloat4_e2m1fn) {
std::string value = this->PrintExpr(op->value);
this->PrintVecStore(op->dest.as_or_throw<TensorVar>().get(), value_ty,
base.Eval(), value);
diff --git a/src/codegen/llvm/codegen_llvm.cc b/src/codegen/llvm/codegen_llvm.cc
index 855026f3..0a54fe46 100644
--- a/src/codegen/llvm/codegen_llvm.cc
+++ b/src/codegen/llvm/codegen_llvm.cc
@@ -87,6 +87,7 @@
#include <llvm/Target/TargetMachine.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/Utils/ModuleUtils.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/runtime/base.h>
#include <tvm/runtime/device_api.h>
#include <tvm/runtime/logging.h>
@@ -100,7 +101,6 @@
#include <utility>
#include <vector>
-#include "../../sym/pattern_match.h"
#include "../build_common.h"
#include "codegen_params.h"
#include "llvm_instance.h"
@@ -664,12 +664,12 @@ void CodeGenLLVM::AddAliasInfo(llvm::Instruction* inst,
const VarNode* buffer_va
}
int64_t base = 0, width = 0;
- sym::PVar<IntImm> pbase, pstride;
- sym::PVar<IntImm> planes;
+ tvm::PVar<IntImm> pbase, pstride;
+ tvm::PVar<IntImm> planes;
// create meta-data for alias analysis
// Use a group of binary tree ranges of memory banks.
int64_t xwith = 0;
- if (sym::ramp(pbase, pstride, planes).Match(index)) {
+ if (tvm::ramp(pbase, pstride, planes).Match(index)) {
if (auto b = pbase.Eval()->value.as<int64_t>(),
w = (planes.Eval()->value * pstride.Eval()->value).as<int64_t>();
b.has_value() && w.has_value()) {
diff --git a/src/ir/prim/int_operator.h b/src/ir/prim/int_operator.h
index ece6ac2e..b4f90011 100644
--- a/src/ir/prim/int_operator.h
+++ b/src/ir/prim/int_operator.h
@@ -28,7 +28,7 @@
namespace tvm {
namespace prim {
-namespace detail {
+namespace details {
/*!
* \brief Perform trunc division of two integers.
@@ -71,7 +71,7 @@ inline int64_t floormod(int64_t x, int64_t y) {
return is_floor_div ? rmod : rmod + y;
}
-} // namespace detail
+} // namespace details
} // namespace prim
} // namespace tvm
#endif // TVM_IR_PRIM_INT_OPERATOR_H_
diff --git a/src/ir/prim/math.cc b/src/ir/prim/math.cc
index 76e2cdda..a2194d61 100644
--- a/src/ir/prim/math.cc
+++ b/src/ir/prim/math.cc
@@ -31,7 +31,7 @@
namespace tvm {
namespace prim {
-using namespace prim::detail;
+using namespace prim::details;
template <size_t N>
static Type InferTypeReturnArgType(const CallNode* call) {
diff --git a/src/ir/prim/op.cc b/src/ir/prim/op.cc
index a160e457..8cd61e1b 100644
--- a/src/ir/prim/op.cc
+++ b/src/ir/prim/op.cc
@@ -17,17 +17,17 @@
* under the License.
*/
#include <tvm/ffi/reflection/registry.h>
+#include <tvm/ir/prim/const_fold.h>
#include <tvm/ir/prim/op.h>
#include <cmath>
-#include "const_fold.h"
#include "op_utils.h"
namespace tvm {
using prim::IsConstInt;
using prim::MakeConst;
-using namespace prim::detail;
+using namespace prim::details;
namespace {
TVM_FFI_INLINE const PrimTypeNode* GetPrimTypeNode(const PrimExpr& expr) {
// Avoid PrimExpr::ty() ObjectRef materialization on binary operator hot
paths.
@@ -71,7 +71,7 @@ bool IsVScaleCall(const PrimExpr& expr) {
}
} // namespace
-namespace prim::detail {
+namespace prim::details {
void BroadcastToMatchLanes(PrimExpr& op_a, PrimExpr& op_b) { // NOLINT(*)
PrimType ty_a = op_a.ty();
PrimType ty_b = op_b.ty();
@@ -183,7 +183,7 @@ void BinaryOpMatchTypes(PrimExpr& lhs, PrimExpr& rhs,
Location loc) { // NOLINT
}
}
-} // namespace prim::detail
+} // namespace prim::details
namespace prim {
// maximum and min limits
PrimExpr max_value(PrimType value_ty, Location loc) {
@@ -388,7 +388,7 @@ PrimExpr operator+(PrimExpr a, PrimExpr b) { return add(a,
b); }
PrimExpr add(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::Add>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::Add>(a, b)) return ret.value();
return prim::Add(a, b, loc);
}
@@ -401,7 +401,7 @@ PrimExpr neg(PrimExpr a, Location loc) {
if (pa) {
ffi::BigInt value = -pa->value;
if (a.ty().MatchesCode(DLDataTypeCode::kDLInt) && a.ty().bits() >= 64) {
- value = prim::detail::GetFoldResult(std::move(value), a.ty());
+ value = prim::details::GetFoldResult(std::move(value), a.ty());
}
return IntImm(a.ty(), std::move(value), loc);
}
@@ -413,20 +413,20 @@ PrimExpr operator-(PrimExpr a, PrimExpr b) { return
sub(a, b); }
PrimExpr sub(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::Sub>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::Sub>(a, b)) return ret.value();
return prim::Sub(a, b, loc);
}
PrimExpr operator*(PrimExpr a, PrimExpr b) { return mul(a, b); }
PrimExpr mul(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::Mul>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::Mul>(a, b)) return ret.value();
return prim::Mul(a, b, loc);
}
PrimExpr div(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::Div>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::Div>(a, b)) return ret.value();
return prim::Div(a, b, loc);
}
@@ -438,7 +438,7 @@ PrimExpr truncdiv(PrimExpr a, PrimExpr b, Location loc) {
PrimExpr truncmod(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::Mod>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::Mod>(a, b)) return ret.value();
return prim::Mod(a, b, loc);
}
@@ -457,7 +457,7 @@ PrimExpr floordiv(PrimExpr a, PrimExpr b, Location loc) {
TVM_FFI_ICHECK(a.ty().MatchesCode(DLDataTypeCode::kDLInt,
DLDataTypeCode::kDLUInt)) << a;
TVM_FFI_ICHECK(b.ty().MatchesCode(DLDataTypeCode::kDLInt,
DLDataTypeCode::kDLUInt)) << b;
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::FloorDiv>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::FloorDiv>(a, b)) return ret.value();
return prim::FloorDiv(a, b, loc);
}
@@ -465,7 +465,7 @@ PrimExpr ceildiv(PrimExpr a, PrimExpr b, Location loc) {
TVM_FFI_ICHECK(a.ty().MatchesCode(DLDataTypeCode::kDLInt,
DLDataTypeCode::kDLUInt)) << a;
TVM_FFI_ICHECK(b.ty().MatchesCode(DLDataTypeCode::kDLInt,
DLDataTypeCode::kDLUInt)) << b;
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::FloorDiv>(a + b - 1, b))
return ret.value();
+ if (auto ret = prim::TryConstFold<prim::FloorDiv>(a + b - 1, b)) return
ret.value();
return prim::FloorDiv(a + b - 1, b, loc);
}
@@ -473,33 +473,33 @@ PrimExpr floormod(PrimExpr a, PrimExpr b, Location loc) {
TVM_FFI_ICHECK(a.ty().MatchesCode(DLDataTypeCode::kDLInt,
DLDataTypeCode::kDLUInt)) << a;
TVM_FFI_ICHECK(b.ty().MatchesCode(DLDataTypeCode::kDLInt,
DLDataTypeCode::kDLUInt)) << b;
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::FloorMod>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::FloorMod>(a, b)) return ret.value();
return prim::FloorMod(a, b, loc);
}
PrimExpr min(PrimExpr a, PrimExpr b, Location loc) {
// inf-aware simplificaiton
- using prim::detail::is_neg_inf;
- using prim::detail::is_pos_inf;
+ using prim::is_neg_inf;
+ using prim::is_pos_inf;
if (is_pos_inf(a)) return b;
if (is_neg_inf(a)) return a;
if (is_pos_inf(b)) return a;
if (is_neg_inf(b)) return b;
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::Min>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::Min>(a, b)) return ret.value();
return prim::Min(a, b, loc);
}
PrimExpr max(PrimExpr a, PrimExpr b, Location loc) {
// inf-aware simplificaiton
- using prim::detail::is_neg_inf;
- using prim::detail::is_pos_inf;
+ using prim::is_neg_inf;
+ using prim::is_pos_inf;
if (is_pos_inf(a)) return a;
if (is_neg_inf(a)) return b;
if (is_pos_inf(b)) return b;
if (is_neg_inf(b)) return a;
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::Max>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::Max>(a, b)) return ret.value();
return prim::Max(a, b, loc);
}
@@ -531,35 +531,35 @@ PrimExpr likely(PrimExpr cond, Location loc) {
PrimExpr operator>(PrimExpr a, PrimExpr b) { return greater(a, b); }
PrimExpr greater(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::GT>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::GT>(a, b)) return ret.value();
return prim::GT(a, b, loc);
}
PrimExpr operator>=(PrimExpr a, PrimExpr b) { return greater_equal(a, b); }
PrimExpr greater_equal(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::GE>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::GE>(a, b)) return ret.value();
return prim::GE(a, b, loc);
}
PrimExpr operator<(PrimExpr a, PrimExpr b) { return less(a, b); }
PrimExpr less(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::LT>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::LT>(a, b)) return ret.value();
return prim::LT(a, b, loc);
}
PrimExpr operator<=(PrimExpr a, PrimExpr b) { return less_equal(a, b); }
PrimExpr less_equal(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::LE>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::LE>(a, b)) return ret.value();
return prim::LE(a, b, loc);
}
PrimExpr operator==(PrimExpr a, PrimExpr b) { return equal(a, b); }
PrimExpr equal(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::EQ>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::EQ>(a, b)) return ret.value();
if (IsVScaleCall(a) && IsVScaleCall(b)) return true;
return prim::EQ(a, b, loc);
}
@@ -567,7 +567,7 @@ PrimExpr equal(PrimExpr a, PrimExpr b, Location loc) {
PrimExpr operator!=(PrimExpr a, PrimExpr b) { return not_equal(a, b); }
PrimExpr not_equal(PrimExpr a, PrimExpr b, Location loc) {
BinaryOpMatchTypes(a, b, loc);
- if (auto ret = prim::detail::TryConstFold<prim::NE>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::NE>(a, b)) return ret.value();
return prim::NE(a, b, loc);
}
@@ -579,7 +579,7 @@ PrimExpr logical_and(PrimExpr a, PrimExpr b, Location loc) {
TVM_FFI_ICHECK(b.ty().MatchesCode(DLDataTypeCode::kDLBool))
<< "Expected boolean argument as RHS of && operator (logical AND), but
received " << b
<< " of type " << b.ty();
- if (auto ret = prim::detail::TryConstFold<prim::And>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::And>(a, b)) return ret.value();
return prim::And(a, b, loc);
}
@@ -591,7 +591,7 @@ PrimExpr logical_or(PrimExpr a, PrimExpr b, Location loc) {
TVM_FFI_ICHECK(b.ty().MatchesCode(DLDataTypeCode::kDLBool))
<< "Expected boolean argument as RHS of || operator (logical OR), but
received " << b
<< " of type " << b.ty();
- if (auto ret = prim::detail::TryConstFold<prim::Or>(a, b)) return
ret.value();
+ if (auto ret = prim::TryConstFold<prim::Or>(a, b)) return ret.value();
return prim::Or(a, b, loc);
}
@@ -600,7 +600,7 @@ PrimExpr logical_not(PrimExpr a, Location loc) {
TVM_FFI_ICHECK(a.ty().MatchesCode(DLDataTypeCode::kDLBool))
<< "Expected boolean argument for ! operator (logical NOT), but received
" << a << " of type "
<< a.ty();
- if (auto ret = prim::detail::TryConstFold<prim::Not>(a)) return ret.value();
+ if (auto ret = prim::TryConstFold<prim::Not>(a)) return ret.value();
return prim::Not(a, loc);
}
@@ -651,7 +651,7 @@ PrimExpr left_shift(PrimExpr a, PrimExpr b, Location loc) {
<< result_ty;
if (pa && pb) {
ffi::BigInt value = pa->value << pb->value;
- if (result_ty.bits() >= 64) value =
prim::detail::GetFoldResult(std::move(value), result_ty);
+ if (result_ty.bits() >= 64) value =
prim::details::GetFoldResult(std::move(value), result_ty);
return IntImm(result_ty, std::move(value), loc);
}
if (pb) {
@@ -733,7 +733,7 @@ PrimExpr prim::IntegerAbs(PrimExpr x, Location loc) {
if (x.ty().MatchesCode(DLDataTypeCode::kDLInt)) {
if (const IntImmNode* px = x.as<IntImmNode>()) {
ffi::BigInt value = px->value < 0 ? -px->value : px->value;
- if (x.ty().bits() >= 64) value =
prim::detail::GetFoldResult(std::move(value), x.ty());
+ if (x.ty().bits() >= 64) value =
prim::details::GetFoldResult(std::move(value), x.ty());
return IntImm(x.ty(), std::move(value), px->loc);
}
return Select(x >= MakeConst(x.ty(), 0), x, -x, loc);
diff --git a/src/ir/prim/op_utils.h b/src/ir/prim/op_utils.h
index 2913bb4b..9ca7b992 100644
--- a/src/ir/prim/op_utils.h
+++ b/src/ir/prim/op_utils.h
@@ -20,8 +20,8 @@
#ifndef TVM_IR_PRIM_OP_UTILS_H_
#define TVM_IR_PRIM_OP_UTILS_H_
#include <tvm/ir/prim/op.h>
-namespace tvm::prim::detail {
+namespace tvm::prim::details {
TVM_TIRX_DLL void BinaryOpMatchTypes(PrimExpr& lhs, PrimExpr& rhs, Location
loc);
-} // namespace tvm::prim::detail
+} // namespace tvm::prim::details
#endif // TVM_IR_PRIM_OP_UTILS_H_
diff --git a/src/ir/prim/symbolic_limits.cc b/src/ir/prim/symbolic_limits.cc
index 49ad9d11..2d991f27 100644
--- a/src/ir/prim/symbolic_limits.cc
+++ b/src/ir/prim/symbolic_limits.cc
@@ -21,15 +21,24 @@
* \file symbolic_limits.cc
* \brief Shared symbolic infinity atoms for primitive operations and integer
analysis.
*/
-#include "const_fold.h"
+#include <tvm/ir/prim/op.h>
namespace tvm {
namespace prim {
-namespace detail {
-PrimExpr SymbolicLimits::pos_inf_ = PrimVar("pos_inf", PrimType::Int(64));
-PrimExpr SymbolicLimits::neg_inf_ = PrimVar("neg_inf", PrimType::Int(64));
+const PrimExpr& pos_inf() {
+ static const PrimExpr value = PrimVar("pos_inf", PrimType::Int(64));
+ return value;
+}
+
+const PrimExpr& neg_inf() {
+ static const PrimExpr value = PrimVar("neg_inf", PrimType::Int(64));
+ return value;
+}
+
+bool is_pos_inf(const PrimExpr& value) { return value.same_as(pos_inf()); }
+
+bool is_neg_inf(const PrimExpr& value) { return value.same_as(neg_inf()); }
-} // namespace detail
} // namespace prim
} // namespace tvm
diff --git a/src/sym/analyzer.cc b/src/sym/analyzer.cc
index 3ca4bcdc..6183fb72 100644
--- a/src/sym/analyzer.cc
+++ b/src/sym/analyzer.cc
@@ -183,7 +183,8 @@ bool AnalyzerObj::CanProveEqual(const PrimExpr& lhs, const
PrimExpr& rhs) {
const auto* clhs = lhs.as<IntImmNode>();
const auto* crhs = rhs.as<IntImmNode>();
if (clhs && crhs) return clhs->value == crhs->value;
- if (is_pos_inf(lhs) || is_neg_inf(lhs) || is_pos_inf(rhs) ||
is_neg_inf(rhs)) {
+ if (prim::is_pos_inf(lhs) || prim::is_neg_inf(lhs) || prim::is_pos_inf(rhs)
||
+ prim::is_neg_inf(rhs)) {
return lhs.same_as(rhs);
}
return CanProve(lhs - rhs == 0);
diff --git a/src/sym/bound_deducer.cc b/src/sym/bound_deducer.cc
index 29b35df3..457cb31a 100644
--- a/src/sym/bound_deducer.cc
+++ b/src/sym/bound_deducer.cc
@@ -27,7 +27,7 @@
#include <tvm/ir/expr_functor.h>
#include <tvm/ir/prim/expr.h>
#include <tvm/sym/analyzer.h>
-#include <tvm/sym/bound.h>
+#include <tvm/sym/int_set.h>
#include <unordered_set>
#include <vector>
@@ -375,7 +375,7 @@ IntSet DeduceBound(PrimExpr v, PrimExpr e, const
ffi::Map<Var, IntSet>& hint_map
BoundDeducer d(v, e, hint_map, relax_map);
d.Deduce();
if (!d.success_) return IntSet::Nothing();
- PrimExpr min = neg_inf(), max = pos_inf();
+ PrimExpr min = prim::neg_inf(), max = prim::pos_inf();
if (d.comp_op == kEqual) {
min = d.result_;
max = d.result_;
diff --git a/src/sym/canonical_simplify.cc b/src/sym/canonical_simplify.cc
index 2a41c2b2..20e9d45b 100644
--- a/src/sym/canonical_simplify.cc
+++ b/src/sym/canonical_simplify.cc
@@ -27,10 +27,10 @@
#include <tvm/ir/cow.h>
#include <tvm/ir/prim/expr.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/sym/analyzer.h>
#include "const_fold.h"
-#include "pattern_match.h"
#include "product_normal_form.h"
#include "rewrite_simplify.h"
diff --git a/src/sym/const_fold.h b/src/sym/const_fold.h
index e1b86f9d..6038ea3e 100644
--- a/src/sym/const_fold.h
+++ b/src/sym/const_fold.h
@@ -24,21 +24,17 @@
#ifndef TVM_SYM_CONST_FOLD_H_
#define TVM_SYM_CONST_FOLD_H_
-#include "../ir/prim/const_fold.h"
+#include <tvm/ir/prim/const_fold.h>
+
#include "int_operator.h"
namespace tvm {
namespace sym {
-using prim::detail::GetFoldResultDoubleRepr;
-using prim::detail::is_neg_inf;
-using prim::detail::is_pos_inf;
-using prim::detail::IsIndexType;
-using prim::detail::IsIndexTypedExpr;
-using prim::detail::neg_inf;
-using prim::detail::pos_inf;
-using prim::detail::SymbolicLimits;
-using prim::detail::TryConstFold;
+using prim::TryConstFold;
+using prim::details::GetFoldResultDoubleRepr;
+using prim::details::IsIndexType;
+using prim::details::IsIndexTypedExpr;
} // namespace sym
} // namespace tvm
diff --git a/src/sym/const_int_bound.cc b/src/sym/const_int_bound.cc
index ca876a12..ff335127 100644
--- a/src/sym/const_int_bound.cc
+++ b/src/sym/const_int_bound.cc
@@ -27,6 +27,7 @@
#include <tvm/ir/op.h>
#include <tvm/ir/prim/expr.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/sym/analyzer.h>
#include <algorithm>
@@ -35,7 +36,6 @@
#include "constraint_extract.h"
#include "int_operator.h"
-#include "pattern_match.h"
namespace tvm {
namespace sym {
diff --git a/src/sym/constraint_extract.cc b/src/sym/constraint_extract.cc
index 51d02518..c58dcffb 100644
--- a/src/sym/constraint_extract.cc
+++ b/src/sym/constraint_extract.cc
@@ -24,10 +24,9 @@
#include "constraint_extract.h"
#include <tvm/ir/prim/expr.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/sym/analyzer.h>
-#include "pattern_match.h"
-
namespace tvm {
namespace sym {
diff --git a/src/sym/int_operator.h b/src/sym/int_operator.h
index 92d4597a..24e6f641 100644
--- a/src/sym/int_operator.h
+++ b/src/sym/int_operator.h
@@ -87,10 +87,10 @@ inline bool WillOverflow<prim::ModNode>(int64_t x, int64_t
y, int64_t min_value,
return y == 0;
}
-using prim::detail::floordiv;
-using prim::detail::floormod;
-using prim::detail::truncdiv;
-using prim::detail::truncmod;
+using prim::details::floordiv;
+using prim::details::floormod;
+using prim::details::truncdiv;
+using prim::details::truncmod;
/*!
* \brief Take GCD of a and b.
diff --git a/src/sym/int_set.cc b/src/sym/int_set.cc
index 50c90fd8..9f061343 100644
--- a/src/sym/int_set.cc
+++ b/src/sym/int_set.cc
@@ -28,6 +28,7 @@
#include <tvm/ir/expr_functor.h>
#include <tvm/ir/prim/expr.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/runtime/logging.h>
#include <tvm/sym/int_set.h>
#include <tvm/sym/iter_affine_map.h>
@@ -40,7 +41,6 @@
#include "constraint_extract.h"
#include "int_operator.h"
#include "interval_set.h"
-#include "pattern_match.h"
namespace tvm {
namespace sym {
@@ -149,9 +149,9 @@ inline IntervalSet Combine<prim::Add>(AnalyzerObj* analyer,
IntervalSet a, Inter
if (a->IsEmpty()) return a;
if (b->IsEmpty()) return b;
PrimExpr min_value =
- a->HasLowerBound() && b->HasLowerBound() ? a->min_value + b->min_value :
neg_inf();
+ a->HasLowerBound() && b->HasLowerBound() ? a->min_value + b->min_value :
prim::neg_inf();
PrimExpr max_value =
- a->HasUpperBound() && b->HasUpperBound() ? a->max_value + b->max_value :
pos_inf();
+ a->HasUpperBound() && b->HasUpperBound() ? a->max_value + b->max_value :
prim::pos_inf();
return IntervalSet(min_value, max_value);
}
@@ -164,9 +164,9 @@ inline IntervalSet Combine<prim::Sub>(AnalyzerObj* analyer,
IntervalSet a, Inter
if (a->IsEmpty()) return a;
if (b->IsEmpty()) return b;
PrimExpr min_value =
- a->HasLowerBound() && b->HasUpperBound() ? a->min_value - b->max_value :
neg_inf();
+ a->HasLowerBound() && b->HasUpperBound() ? a->min_value - b->max_value :
prim::neg_inf();
PrimExpr max_value =
- a->HasUpperBound() && b->HasLowerBound() ? a->max_value - b->min_value :
pos_inf();
+ a->HasUpperBound() && b->HasLowerBound() ? a->max_value - b->min_value :
prim::pos_inf();
return IntervalSet(min_value, max_value);
}
@@ -185,12 +185,12 @@ inline IntervalSet Combine<prim::Mul>(AnalyzerObj*
analyzer, IntervalSet a, Inte
if (IsZero(b->min_value)) return b;
if (IsOne(b->min_value)) return a;
if (analyzer->CanProveGreaterEqual(b->min_value, 0)) {
- PrimExpr min_value = a->HasLowerBound() ? a->min_value * b->min_value :
neg_inf();
- PrimExpr max_value = a->HasUpperBound() ? a->max_value * b->min_value :
pos_inf();
+ PrimExpr min_value = a->HasLowerBound() ? a->min_value * b->min_value :
prim::neg_inf();
+ PrimExpr max_value = a->HasUpperBound() ? a->max_value * b->min_value :
prim::pos_inf();
return IntervalSet(min_value, max_value);
} else if (analyzer->CanProveGreaterEqual(-b->min_value, 1)) {
- PrimExpr min_value = a->HasUpperBound() ? a->max_value * b->min_value :
neg_inf();
- PrimExpr max_value = a->HasLowerBound() ? a->min_value * b->min_value :
pos_inf();
+ PrimExpr min_value = a->HasUpperBound() ? a->max_value * b->min_value :
prim::neg_inf();
+ PrimExpr max_value = a->HasLowerBound() ? a->min_value * b->min_value :
prim::pos_inf();
return IntervalSet(min_value, max_value);
} else if (a->HasUpperBound() && a->HasLowerBound()) {
PrimExpr sign = b->min_value >= IntImm(b->min_value.ty().WithLanes(1),
0);
@@ -218,12 +218,12 @@ inline IntervalSet Combine<prim::Div>(AnalyzerObj*
analyzer, IntervalSet a, Inte
if (IsOne(b->min_value)) return a;
// no relaxation is needed in here due to set is inclusive
if (analyzer->CanProveGreaterEqual(b->min_value, 0)) {
- PrimExpr min_value = a->HasLowerBound() ? a->min_value / b->min_value :
neg_inf();
- PrimExpr max_value = a->HasUpperBound() ? a->max_value / b->min_value :
pos_inf();
+ PrimExpr min_value = a->HasLowerBound() ? a->min_value / b->min_value :
prim::neg_inf();
+ PrimExpr max_value = a->HasUpperBound() ? a->max_value / b->min_value :
prim::pos_inf();
return IntervalSet(min_value, max_value);
} else if (analyzer->CanProveGreaterEqual(-b->min_value, 1)) {
- PrimExpr min_value = a->HasUpperBound() ? a->max_value / b->min_value :
neg_inf();
- PrimExpr max_value = a->HasLowerBound() ? a->min_value / b->min_value :
pos_inf();
+ PrimExpr min_value = a->HasUpperBound() ? a->max_value / b->min_value :
prim::neg_inf();
+ PrimExpr max_value = a->HasLowerBound() ? a->min_value / b->min_value :
prim::pos_inf();
return IntervalSet(min_value, max_value);
} else if (a->HasUpperBound() && a->HasLowerBound()) {
PrimExpr sign = b->min_value >= IntImm(b->min_value.ty().WithLanes(1),
0);
@@ -280,12 +280,16 @@ inline IntervalSet Combine<prim::FloorDiv>(AnalyzerObj*
analyzer, IntervalSet a,
if (IsOne(b->min_value)) return a;
// no relaxation is needed in here due to set is inclusive
if (analyzer->CanProveGreaterEqual(b->min_value, 0)) {
- PrimExpr min_value = a->HasLowerBound() ? floordiv(a->min_value,
b->min_value) : neg_inf();
- PrimExpr max_value = a->HasUpperBound() ? floordiv(a->max_value,
b->min_value) : pos_inf();
+ PrimExpr min_value =
+ a->HasLowerBound() ? floordiv(a->min_value, b->min_value) :
prim::neg_inf();
+ PrimExpr max_value =
+ a->HasUpperBound() ? floordiv(a->max_value, b->min_value) :
prim::pos_inf();
return IntervalSet(min_value, max_value);
} else if (analyzer->CanProveGreaterEqual(-b->min_value, 1)) {
- PrimExpr min_value = a->HasUpperBound() ? floordiv(a->max_value,
b->min_value) : neg_inf();
- PrimExpr max_value = a->HasLowerBound() ? floordiv(a->min_value,
b->min_value) : pos_inf();
+ PrimExpr min_value =
+ a->HasUpperBound() ? floordiv(a->max_value, b->min_value) :
prim::neg_inf();
+ PrimExpr max_value =
+ a->HasLowerBound() ? floordiv(a->min_value, b->min_value) :
prim::pos_inf();
return IntervalSet(min_value, max_value);
} else if (a->HasUpperBound() && a->HasLowerBound()) {
PrimExpr sign = b->min_value >= IntImm(b->min_value.ty().WithLanes(1),
0);
@@ -315,12 +319,12 @@ inline IntervalSet Combine<prim::FloorMod>(AnalyzerObj*
analyzer, IntervalSet a,
if (analyzer->CanProveGreaterEqual(divisor, 0)) {
if (divisor.as<IntImmNode>()) {
// a mod b = a - (a / b) * b if a_max / b == a_min / b
- auto qmax = a->HasUpperBound() ? floordiv(a->max_value, divisor) :
pos_inf();
- auto qmin = a->HasLowerBound() ? floordiv(a->min_value, divisor) :
neg_inf();
+ auto qmax = a->HasUpperBound() ? floordiv(a->max_value, divisor) :
prim::pos_inf();
+ auto qmin = a->HasLowerBound() ? floordiv(a->min_value, divisor) :
prim::neg_inf();
// We can compare +/- inf against each other, but cannot use
// operator== between the symbolic limits and an integer.
- bool qmin_is_symbolic_limit = is_pos_inf(qmin) || is_neg_inf(qmin);
- bool qmax_is_symbolic_limit = is_pos_inf(qmax) || is_neg_inf(qmax);
+ bool qmin_is_symbolic_limit = prim::is_pos_inf(qmin) ||
prim::is_neg_inf(qmin);
+ bool qmax_is_symbolic_limit = prim::is_pos_inf(qmax) ||
prim::is_neg_inf(qmax);
bool compatible_dtypes = qmin_is_symbolic_limit ==
qmax_is_symbolic_limit;
if (compatible_dtypes && analyzer->CanProve(qmax == qmin)) {
auto tmax = a->max_value - divisor * qmin;
@@ -572,10 +576,10 @@ class IntervalSetEvaluator : public
tvm::ExprFunctor<IntervalSet(const Expr&)> {
}
PrimExpr min_value = value_set->HasLowerBound()
? prim::cast(value_set->min_value,
op->ty.as_or_throw<PrimType>())
- : neg_inf();
+ : prim::neg_inf();
PrimExpr max_value = value_set->HasUpperBound()
? prim::cast(value_set->max_value,
op->ty.as_or_throw<PrimType>())
- : pos_inf();
+ : prim::pos_inf();
return IntervalSet(min_value, max_value);
}
@@ -735,25 +739,25 @@ std::vector<std::pair<Var, IntSet>>
IntSetAnalyzer::Impl::DetectBoundInfo(
std::vector<std::pair<Var, IntSet>> bounds;
for (const PrimExpr& subconstraint : ExtractConstraints(constraint)) {
if ((x <= limit).Match(subconstraint)) {
- bounds.push_back({x.Eval(), IntSet::Interval(SymbolicLimits::neg_inf_,
limit.Eval())});
+ bounds.push_back({x.Eval(), IntSet::Interval(prim::neg_inf(),
limit.Eval())});
} else if ((x < limit).Match(subconstraint)) {
- bounds.push_back({x.Eval(), IntSet::Interval(SymbolicLimits::neg_inf_,
limit.Eval() - 1)});
+ bounds.push_back({x.Eval(), IntSet::Interval(prim::neg_inf(),
limit.Eval() - 1)});
} else if ((x >= limit).Match(subconstraint)) {
- bounds.push_back({x.Eval(), IntSet::Interval(limit.Eval(),
SymbolicLimits::pos_inf_)});
+ bounds.push_back({x.Eval(), IntSet::Interval(limit.Eval(),
prim::pos_inf())});
} else if ((x > limit).Match(subconstraint)) {
- bounds.push_back({x.Eval(), IntSet::Interval(limit.Eval() + 1,
SymbolicLimits::pos_inf_)});
+ bounds.push_back({x.Eval(), IntSet::Interval(limit.Eval() + 1,
prim::pos_inf())});
} else if ((x == limit).Match(subconstraint)) {
bounds.push_back({x.Eval(), IntSet::SinglePoint(limit.Eval())});
}
if ((limit >= x).Match(subconstraint)) {
- bounds.push_back({x.Eval(), IntSet::Interval(SymbolicLimits::neg_inf_,
limit.Eval())});
+ bounds.push_back({x.Eval(), IntSet::Interval(prim::neg_inf(),
limit.Eval())});
} else if ((limit > x).Match(subconstraint)) {
- bounds.push_back({x.Eval(), IntSet::Interval(SymbolicLimits::neg_inf_,
limit.Eval() - 1)});
+ bounds.push_back({x.Eval(), IntSet::Interval(prim::neg_inf(),
limit.Eval() - 1)});
} else if ((limit <= x).Match(subconstraint)) {
- bounds.push_back({x.Eval(), IntSet::Interval(limit.Eval(),
SymbolicLimits::pos_inf_)});
+ bounds.push_back({x.Eval(), IntSet::Interval(limit.Eval(),
prim::pos_inf())});
} else if ((limit < x).Match(subconstraint)) {
- bounds.push_back({x.Eval(), IntSet::Interval(limit.Eval() + 1,
SymbolicLimits::pos_inf_)});
+ bounds.push_back({x.Eval(), IntSet::Interval(limit.Eval() + 1,
prim::pos_inf())});
} else if ((limit == x).Match(subconstraint)) {
bounds.push_back({x.Eval(), IntSet::SinglePoint(limit.Eval())});
}
@@ -977,9 +981,11 @@ IntSet UnionLowerBound(const ffi::Array<IntSet>& sets) {
max_inclusive = std::move(new_max_inclusive);
continue;
}
- bool bound_1 = is_neg_inf(new_min_inclusive) ||
is_pos_inf(max_inclusive.value()) ||
+ bool bound_1 = prim::is_neg_inf(new_min_inclusive) ||
+ prim::is_pos_inf(max_inclusive.value()) ||
analyzer->CanProve(new_min_inclusive <=
max_inclusive.value() + 1);
- bool bound_2 = is_neg_inf(min_inclusive.value()) ||
is_pos_inf(new_max_inclusive) ||
+ bool bound_2 = prim::is_neg_inf(min_inclusive.value()) ||
+ prim::is_pos_inf(new_max_inclusive) ||
analyzer->CanProve(min_inclusive.value() <=
new_max_inclusive + 1);
if (bound_1 && bound_2) {
min_inclusive = min(min_inclusive.value(), new_min_inclusive);
@@ -1267,8 +1273,8 @@ TVM_FFI_STATIC_INIT_BLOCK() {
Analyzer analyzer = opt_analyzer.has_value() ?
opt_analyzer.value() : Analyzer();
return EstimateRegionUpperBound(region, var_dom, predicate,
analyzer);
})
- .def("sym.PosInf", []() { return SymbolicLimits::pos_inf_; })
- .def("sym.NegInf", []() { return SymbolicLimits::neg_inf_; })
+ .def("sym.PosInf", []() { return prim::pos_inf(); })
+ .def("sym.NegInf", []() { return prim::neg_inf(); })
.def("sym.UnionLowerBound", UnionLowerBound);
}
diff --git a/src/sym/interval_set.h b/src/sym/interval_set.h
index 1aee24ae..46e767a2 100644
--- a/src/sym/interval_set.h
+++ b/src/sym/interval_set.h
@@ -64,9 +64,9 @@ class IntervalSetObj : public IntSetObj {
}
/*! \return Whether the interval has upper bound. */
- bool HasUpperBound() const { return !is_pos_inf(max_value) && !IsEmpty(); }
+ bool HasUpperBound() const { return !prim::is_pos_inf(max_value) &&
!IsEmpty(); }
/*! \return Whether the interval has lower bound. */
- bool HasLowerBound() const { return !is_neg_inf(min_value) && !IsEmpty(); }
+ bool HasLowerBound() const { return !prim::is_neg_inf(min_value) &&
!IsEmpty(); }
/*! \return Whether the interval is a single point. */
bool IsSinglePoint() const {
// NOTE: we are only doing cheap check as this is a frequently called
routine,
@@ -77,10 +77,10 @@ class IntervalSetObj : public IntSetObj {
/*! \return whether interval represent nothing */
bool IsEmpty() const {
// during computations, either extreme could occur.
- return is_pos_inf(min_value) || is_neg_inf(max_value);
+ return prim::is_pos_inf(min_value) || prim::is_neg_inf(max_value);
}
/*! \return whether interval represent everything */
- bool IsEverything() const { return is_neg_inf(min_value) &&
is_pos_inf(max_value); }
+ bool IsEverything() const { return prim::is_neg_inf(min_value) &&
prim::is_pos_inf(max_value); }
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("sym.IntervalSet", IntervalSetObj,
IntSetObj);
};
@@ -109,12 +109,12 @@ class IntervalSet : public IntSet {
* \param value The value to be represented.
* \return The result set.
*/
- static IntervalSet Everything() { return IntervalSet(neg_inf(), pos_inf()); }
+ static IntervalSet Everything() { return IntervalSet(prim::neg_inf(),
prim::pos_inf()); }
/*!
* \brief Create an empty eet.
* \return The result set.
*/
- static IntervalSet Empty() { return IntervalSet(pos_inf(), neg_inf()); }
+ static IntervalSet Empty() { return IntervalSet(prim::pos_inf(),
prim::neg_inf()); }
TVM_DEFINE_OBJECT_REF_COW_METHOD(IntervalSetObj);
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(IntervalSet, IntSet,
IntervalSetObj);
diff --git a/src/sym/iter_affine_map.cc b/src/sym/iter_affine_map.cc
index 813bf66f..1189aac7 100644
--- a/src/sym/iter_affine_map.cc
+++ b/src/sym/iter_affine_map.cc
@@ -27,6 +27,7 @@
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ir/expr_functor.h>
#include <tvm/ir/prim/expr.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/sym/analyzer.h>
#include <tvm/sym/iter_affine_map.h>
@@ -34,7 +35,6 @@
#include <utility>
#include "const_fold.h"
-#include "pattern_match.h"
#include "product_normal_form.h"
namespace tvm {
@@ -1376,7 +1376,7 @@ struct IterConstraint {
*/
bool MatchBoundConstraints(PrimExpr pred, ffi::Map<PrimVar, Range>*
input_iters,
std::vector<IterConstraint>* result) {
- sym::PVar<PrimExpr> lhs, rhs, rest;
+ tvm::PVar<PrimExpr> lhs, rhs, rest;
std::unordered_set<const VarNode*> input_iter_nodes;
for (const auto& [var, _] : *input_iters) {
input_iter_nodes.insert(var.get());
diff --git a/src/sym/known_comparison_analyzer.cc
b/src/sym/known_comparison_analyzer.cc
index ab9850c2..3908b26d 100644
--- a/src/sym/known_comparison_analyzer.cc
+++ b/src/sym/known_comparison_analyzer.cc
@@ -21,13 +21,13 @@
*/
#include <tvm/ir/prim/expr.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/sym/analyzer.h>
#include <optional>
#include <vector>
#include "constraint_extract.h"
-#include "pattern_match.h"
namespace tvm {
namespace sym {
diff --git a/src/sym/modular_set.cc b/src/sym/modular_set.cc
index d765747f..0ea3d3f0 100644
--- a/src/sym/modular_set.cc
+++ b/src/sym/modular_set.cc
@@ -26,6 +26,7 @@
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ir/expr_functor.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/sym/analyzer.h>
#include <limits>
@@ -33,8 +34,6 @@
#include <unordered_map>
#include <utility>
-#include "pattern_match.h"
-
namespace tvm {
namespace sym {
using namespace tvm::prim;
diff --git a/src/sym/rewrite_simplify.cc b/src/sym/rewrite_simplify.cc
index 716832d2..f72a48d9 100644
--- a/src/sym/rewrite_simplify.cc
+++ b/src/sym/rewrite_simplify.cc
@@ -29,6 +29,7 @@
#include <tvm/ir/op.h>
#include <tvm/ir/prim/expr.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/sym/analyzer.h>
#include <algorithm>
@@ -38,7 +39,6 @@
#include "const_fold.h"
#include "constraint_extract.h"
-#include "pattern_match.h"
namespace tvm {
namespace sym {
@@ -52,17 +52,17 @@ TVM_FFI_INLINE bool IsVectorExpr(const ExprNode* expr) {
TVM_FFI_STATIC_INIT_BLOCK() { RewriteSimplifierStatsObj::RegisterReflection();
}
-// Note: When using matches_one_of or PMatchesOneOf alongside these
+// Note: When using MatchesOneOf or PMatchesOneOf alongside these
// macros, be careful which patterns are used in the ResExpr. While
// the different source expressions may be in terms of different PVar,
// the ResExpr should only contain patterns that are defined in
// *every* SrcExpr given.
//
// Allowed (replacement does not use either c1 or y):
-// TVM_TRY_REWRITE(matches_one_of(x + c1 - c1, x + y - y), x)
+// TVM_TRY_REWRITE(MatchesOneOf(x + c1 - c1, x + y - y), x)
//
// Forbidden (c3 undefined if the first pattern matches):
-// TVM_TRY_REWRITE(matches_one_of(floormod(x*c1,c2), floormod(x*c1 + c3,
c2)),
+// TVM_TRY_REWRITE(MatchesOneOf(floormod(x*c1,c2), floormod(x*c1 + c3,
c2)),
// floormod(x*floormod(c1,c2) + floormod(c3,c2), c2))
// macro for doing simple rewrite
@@ -311,9 +311,9 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::AddNode* op,
// mul co-efficient folding
TVM_TRY_REWRITE(x + x, x * 2);
- TVM_TRY_REWRITE(matches_one_of(x * y + x, y * x + x, x + y * x, x + x *
y), (y + 1) * x);
+ TVM_TRY_REWRITE(MatchesOneOf(x * y + x, y * x + x, x + y * x, x + x * y),
(y + 1) * x);
- TVM_TRY_REWRITE(matches_one_of(x * y + x * z, y * x + x * z, x * y + z *
x, y * x + z * x),
+ TVM_TRY_REWRITE(MatchesOneOf(x * y + x * z, y * x + x * z, x * y + z * x,
y * x + z * x),
(y + z) * x);
// DivMod rules
@@ -321,8 +321,8 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::AddNode* op,
TVM_TRY_REWRITE(truncdiv(x, c1) * c1 + truncmod(x, c1), x);
// floor div
TVM_TRY_REWRITE(
- matches_one_of(floordiv(x, y) * y + floormod(x, y), y * floordiv(x, y)
+ floormod(x, y),
- floormod(x, y) + floordiv(x, y) * y, floormod(x, y) + y
* floordiv(x, y)),
+ MatchesOneOf(floordiv(x, y) * y + floormod(x, y), y * floordiv(x, y) +
floormod(x, y),
+ floormod(x, y) + floordiv(x, y) * y, floormod(x, y) + y *
floordiv(x, y)),
x);
TVM_TRY_REWRITE_IF(floordiv(floormod(x, c2) + c1, c2) + floordiv(x, c2),
floordiv(x + c1, c2),
@@ -342,9 +342,8 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::AddNode* op,
// canonicalization rule
// will try rewrite again after canonicalization.
- TVM_TRY_RECURSIVE_REWRITE(matches_one_of(x + (c1 - y), (c1 - y) + x), (x -
y) + c1);
- TVM_TRY_RECURSIVE_REWRITE(matches_one_of((x + c1) + y, x + (c1 + y), x +
(y + c1)),
- (x + y) + c1);
+ TVM_TRY_RECURSIVE_REWRITE(MatchesOneOf(x + (c1 - y), (c1 - y) + x), (x -
y) + c1);
+ TVM_TRY_RECURSIVE_REWRITE(MatchesOneOf((x + c1) + y, x + (c1 + y), x + (y
+ c1)), (x + y) + c1);
TVM_TRY_RECURSIVE_REWRITE(x + max(y, z), max(y, z) + x);
TVM_TRY_RECURSIVE_REWRITE(x + min(y, z), min(y, z) + x);
@@ -418,19 +417,19 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::SubNode* op,
if (IsIndexTypedExpr(op)) {
// Index rules
// cancelation rules
- TVM_TRY_REWRITE(matches_one_of((x + y) - y, (y + x) - y), x);
- TVM_TRY_REWRITE(matches_one_of(x - (y + x), x - (x + y)), 0 - y);
+ TVM_TRY_REWRITE(MatchesOneOf((x + y) - y, (y + x) - y), x);
+ TVM_TRY_REWRITE(MatchesOneOf(x - (y + x), x - (x + y)), 0 - y);
- TVM_TRY_REWRITE(matches_one_of(min(x, y) - y, x - max(y, x)), min(x - y,
0));
- TVM_TRY_REWRITE(matches_one_of(x - max(x, y), min(y, x) - y), min(0, x -
y));
- TVM_TRY_REWRITE(matches_one_of(max(x, y) - y, x - min(y, x)), max(x - y,
0));
- TVM_TRY_REWRITE(matches_one_of(x - min(x, y), max(y, x) - y), max(0, x -
y));
+ TVM_TRY_REWRITE(MatchesOneOf(min(x, y) - y, x - max(y, x)), min(x - y, 0));
+ TVM_TRY_REWRITE(MatchesOneOf(x - max(x, y), min(y, x) - y), min(0, x - y));
+ TVM_TRY_REWRITE(MatchesOneOf(max(x, y) - y, x - min(y, x)), max(x - y, 0));
+ TVM_TRY_REWRITE(MatchesOneOf(x - min(x, y), max(y, x) - y), max(0, x - y));
// mul co-efficient folding: pefer co-effiicent to stay at rhs
TVM_TRY_REWRITE(x - x, ZeroWithTypeLike(x));
- TVM_TRY_REWRITE(matches_one_of(x * y - x, y * x - x), (y - 1) * x);
- TVM_TRY_REWRITE(matches_one_of(x - x * y, x - y * x), (1 - y) * x);
- TVM_TRY_REWRITE(matches_one_of(x * y - x * z, y * x - x * z, x * y - z *
x, y * x - z * x),
+ TVM_TRY_REWRITE(MatchesOneOf(x * y - x, y * x - x), (y - 1) * x);
+ TVM_TRY_REWRITE(MatchesOneOf(x - x * y, x - y * x), (1 - y) * x);
+ TVM_TRY_REWRITE(MatchesOneOf(x * y - x * z, y * x - x * z, x * y - z * x,
y * x - z * x),
(y - z) * x);
// constant cancelation
@@ -439,28 +438,28 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::SubNode* op,
// cancelization rule involving 4 operands
TVM_TRY_REWRITE(
- matches_one_of((x + y) - (x + z), (x + y) - (z + x), (y + x) - (z +
x), (y + x) - (x + z)),
+ MatchesOneOf((x + y) - (x + z), (x + y) - (z + x), (y + x) - (z + x),
(y + x) - (x + z)),
y - z);
- TVM_TRY_REWRITE(matches_one_of(min(x + y, z) - x, min(y + x, z) - x),
min(y, z - x));
- TVM_TRY_REWRITE(matches_one_of(min(z, x + y) - x, min(z, y + x) - x),
min(z - x, y));
+ TVM_TRY_REWRITE(MatchesOneOf(min(x + y, z) - x, min(y + x, z) - x), min(y,
z - x));
+ TVM_TRY_REWRITE(MatchesOneOf(min(z, x + y) - x, min(z, y + x) - x), min(z
- x, y));
- TVM_TRY_REWRITE(matches_one_of(max(x + y, z) - x, max(y + x, z) - x),
max(y, z - x));
- TVM_TRY_REWRITE(matches_one_of(max(z, x + y) - x, max(z, y + x) - x),
max(z - x, y));
+ TVM_TRY_REWRITE(MatchesOneOf(max(x + y, z) - x, max(y + x, z) - x), max(y,
z - x));
+ TVM_TRY_REWRITE(MatchesOneOf(max(z, x + y) - x, max(z, y + x) - x), max(z
- x, y));
- TVM_TRY_REWRITE(matches_one_of(x - min(x + y, z), x - min(y + x, z)),
max(0 - y, x - z));
- TVM_TRY_REWRITE(matches_one_of(x - min(z, x + y), x - min(z, y + x)),
max(x - z, 0 - y));
- TVM_TRY_REWRITE(matches_one_of(x - max(x + y, z), x - max(y + x, z)),
min(0 - y, x - z));
- TVM_TRY_REWRITE(matches_one_of(x - max(z, x + y), x - max(z, y + x)),
min(x - z, 0 - y));
+ TVM_TRY_REWRITE(MatchesOneOf(x - min(x + y, z), x - min(y + x, z)), max(0
- y, x - z));
+ TVM_TRY_REWRITE(MatchesOneOf(x - min(z, x + y), x - min(z, y + x)), max(x
- z, 0 - y));
+ TVM_TRY_REWRITE(MatchesOneOf(x - max(x + y, z), x - max(y + x, z)), min(0
- y, x - z));
+ TVM_TRY_REWRITE(MatchesOneOf(x - max(z, x + y), x - max(z, y + x)), min(x
- z, 0 - y));
TVM_TRY_REWRITE(min(x, y) - min(y, x), ZeroWithTypeLike(x));
TVM_TRY_REWRITE(max(x, y) - max(y, x), ZeroWithTypeLike(x));
- TVM_TRY_REWRITE_IF(matches_one_of(min(b1, b2) - min(s1, s2), min(b1, b2) -
min(s2, s1)),
- b1 - s1, CanProveEqual(((b1 - s1) - (b2 - s2)).Eval(),
0));
+ TVM_TRY_REWRITE_IF(MatchesOneOf(min(b1, b2) - min(s1, s2), min(b1, b2) -
min(s2, s1)), b1 - s1,
+ CanProveEqual(((b1 - s1) - (b2 - s2)).Eval(), 0));
- TVM_TRY_REWRITE_IF(matches_one_of(max(b1, b2) - max(s1, s2), max(b1, b2) -
max(s2, s1)),
- b1 - s1, CanProveEqual(((b1 - s1) - (b2 - s2)).Eval(),
0));
+ TVM_TRY_REWRITE_IF(MatchesOneOf(max(b1, b2) - max(s1, s2), max(b1, b2) -
max(s2, s1)), b1 - s1,
+ CanProveEqual(((b1 - s1) - (b2 - s2)).Eval(), 0));
// DivMod rules
// trucdiv
@@ -602,8 +601,8 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::MulNode* op,
// Vector rules
if (IsVectorExpr(op)) {
TVM_TRY_REWRITE(broadcast(x, lanes) * broadcast(y, lanes), broadcast(x *
y, lanes));
- TVM_TRY_REWRITE(matches_one_of(ramp(b1, s1, lanes) * broadcast(x, lanes),
- broadcast(x, lanes) * ramp(b1, s1, lanes)),
+ TVM_TRY_REWRITE(MatchesOneOf(ramp(b1, s1, lanes) * broadcast(x, lanes),
+ broadcast(x, lanes) * ramp(b1, s1, lanes)),
ramp(b1 * x, s1 * x, lanes));
TVM_TRY_REWRITE_IF(broadcast(c3, lanes) * x, broadcast(c3, lanes),
c3.Eval()->value == 0.0f);
}
@@ -612,7 +611,7 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::MulNode* op,
// constant simplification rule
TVM_TRY_REWRITE((x + c1) * c2, x * c2 + c1 * c2);
TVM_TRY_REWRITE((x * c1) * c2, x * (c1 * c2));
- TVM_TRY_REWRITE(matches_one_of(min(x, y) * max(x, y), max(x, y) * min(x,
y)), x * y);
+ TVM_TRY_REWRITE(MatchesOneOf(min(x, y) * max(x, y), max(x, y) * min(x,
y)), x * y);
// Two representations of const*ceildiv(x, c1)
TVM_TRY_REWRITE_IF(floordiv(x - floormod(x, c2), c1) * c1, x - floormod(x,
c2),
@@ -699,7 +698,7 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::DivNode* op,
}
TVM_TRY_REWRITE(truncdiv(x, x), OneWithTypeLike(x));
- TVM_TRY_REWRITE(matches_one_of(truncdiv(x * c1, x), truncdiv(c1 * x, x)),
c1);
+ TVM_TRY_REWRITE(MatchesOneOf(truncdiv(x * c1, x), truncdiv(c1 * x, x)),
c1);
// Rules involving 2-operands.
TVM_TRY_REWRITE_IF(truncdiv(x * c1 + y, c2), x * truncdiv(c1, c2) +
truncdiv(y, c2),
@@ -758,23 +757,23 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::DivNode* op,
c1.Eval()->value % c2.Eval()->value == 0 &&
CanProveGreaterEqual(x.Eval(), 0));
- TVM_TRY_REWRITE_IF(matches_one_of(truncdiv(x + y, x), truncdiv(y + x, x)),
truncdiv(y, x) + 1,
+ TVM_TRY_REWRITE_IF(MatchesOneOf(truncdiv(x + y, x), truncdiv(y + x, x)),
truncdiv(y, x) + 1,
CanProveGreaterEqual(x.Eval(), 0) &&
CanProveGreaterEqual(y.Eval(), 0));
TVM_TRY_REWRITE_IF(
- matches_one_of(truncdiv((x + y) + z, x), truncdiv((y + x) + z, x),
truncdiv(y + (z + x), x),
- truncdiv(y + (x + z), x)),
+ MatchesOneOf(truncdiv((x + y) + z, x), truncdiv((y + x) + z, x),
truncdiv(y + (z + x), x),
+ truncdiv(y + (x + z), x)),
truncdiv(y + z, x) + 1,
CanProveGreaterEqual(x.Eval(), 0) && CanProveGreaterEqual((y +
z).Eval(), 0));
- TVM_TRY_REWRITE_IF(matches_one_of(truncdiv(x * y, y), truncdiv(y * x, y)),
x,
+ TVM_TRY_REWRITE_IF(MatchesOneOf(truncdiv(x * y, y), truncdiv(y * x, y)), x,
CanProveGreaterEqual(x.Eval(), 0) &&
CanProveGreaterEqual(y.Eval(), 0));
- TVM_TRY_REWRITE_IF(matches_one_of(truncdiv(x * z + y, z), truncdiv(z * x +
y, z)),
+ TVM_TRY_REWRITE_IF(MatchesOneOf(truncdiv(x * z + y, z), truncdiv(z * x +
y, z)),
x + truncdiv(y, z),
CanProveGreaterEqual(x.Eval(), 0) &&
CanProveGreaterEqual(y.Eval(), 0) &&
CanProveGreaterEqual(z.Eval(), 0));
- TVM_TRY_REWRITE_IF(matches_one_of(truncdiv(y + x * z, z), truncdiv(y + z *
x, z)),
+ TVM_TRY_REWRITE_IF(MatchesOneOf(truncdiv(y + x * z, z), truncdiv(y + z *
x, z)),
truncdiv(y, z) + x,
CanProveGreaterEqual(x.Eval(), 0) &&
CanProveGreaterEqual(y.Eval(), 0) &&
CanProveGreaterEqual(z.Eval(), 0));
@@ -956,7 +955,7 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::FloorDivNode*
}
TVM_TRY_REWRITE(floordiv(x, x), OneWithTypeLike(x));
- TVM_TRY_REWRITE(matches_one_of(floordiv(x * c1, x), floordiv(c1 * x, x)),
c1);
+ TVM_TRY_REWRITE(MatchesOneOf(floordiv(x * c1, x), floordiv(c1 * x, x)),
c1);
TVM_TRY_REWRITE(floordiv(floormod(x, 2) + 1, 2), floormod(x, 2));
@@ -981,7 +980,7 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::FloorDivNode*
c2.Eval()->value % c1.Eval()->value == 0 &&
CanProveEqual(floordiv(y.Eval() + z.Eval(),
c1.Eval()), 0));
- TVM_TRY_REWRITE_IF(matches_one_of(floordiv(x * c1 - y + z, c2), floordiv(x
* c1 + z - y, c2)),
+ TVM_TRY_REWRITE_IF(MatchesOneOf(floordiv(x * c1 - y + z, c2), floordiv(x *
c1 + z - y, c2)),
x * floordiv(c1, c2) + floordiv(z - y, c2),
c2.Eval()->value > 0 && c1.Eval()->value %
c2.Eval()->value == 0);
@@ -999,19 +998,19 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::FloorDivNode*
TVM_TRY_REWRITE_IF(floordiv(x * c1, x * c2), floordiv(c1, c2),
c2.Eval()->value > 0);
- TVM_TRY_REWRITE_IF(matches_one_of(floordiv(x + y, x), floordiv(y + x, x)),
floordiv(y, x) + 1,
+ TVM_TRY_REWRITE_IF(MatchesOneOf(floordiv(x + y, x), floordiv(y + x, x)),
floordiv(y, x) + 1,
CanProveGreaterEqual(x.Eval(), 0));
- TVM_TRY_REWRITE_IF(matches_one_of(floordiv((x + y) + z, x), floordiv((y +
x) + z, x),
- floordiv(y + (z + x), x), floordiv(y +
(x + z), x)),
+ TVM_TRY_REWRITE_IF(MatchesOneOf(floordiv((x + y) + z, x), floordiv((y + x)
+ z, x),
+ floordiv(y + (z + x), x), floordiv(y + (x
+ z), x)),
floordiv(y + z, x) + 1, CanProveGreaterEqual(x.Eval(),
0));
- TVM_TRY_REWRITE_IF(matches_one_of(floordiv(x * y, y), floordiv(y * x, y)),
x,
+ TVM_TRY_REWRITE_IF(MatchesOneOf(floordiv(x * y, y), floordiv(y * x, y)), x,
CanProveGreaterEqual(y.Eval(), 0));
- TVM_TRY_REWRITE_IF(matches_one_of(floordiv(x * z + y, z), floordiv(z * x +
y, z)),
+ TVM_TRY_REWRITE_IF(MatchesOneOf(floordiv(x * z + y, z), floordiv(z * x +
y, z)),
x + floordiv(y, z), CanProveGreaterEqual(z.Eval(), 0));
- TVM_TRY_REWRITE_IF(matches_one_of(floordiv(y + x * z, z), floordiv(y + z *
x, z)),
+ TVM_TRY_REWRITE_IF(MatchesOneOf(floordiv(y + x * z, z), floordiv(y + z *
x, z)),
floordiv(y, z) + x, CanProveGreaterEqual(z.Eval(), 0));
TVM_TRY_REWRITE_IF(floordiv(x * z * c1 + y, z * c1), x + floordiv(y, z *
c1),
CanProveGreaterEqual(z.Eval() * c1.Eval(), 0));
@@ -1150,15 +1149,15 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::FloorModNode*
TVM_TRY_REWRITE_IF(floormod(x * c1, x * c2), x * floormod(c1, c2),
c2.Eval()->value != 0);
- TVM_TRY_REWRITE(matches_one_of(floormod(x * y, y), floormod(y * x, y)),
ZeroWithTypeLike(y));
+ TVM_TRY_REWRITE(MatchesOneOf(floormod(x * y, y), floormod(y * x, y)),
ZeroWithTypeLike(y));
// x = ay + b, then (ay + b + (ny - ay - b) % y) % y -> (b + (-b) % y) % y
-> 0
TVM_TRY_REWRITE_IF(
- matches_one_of(floormod(x + floormod(z, y), y), floormod(floormod(z,
y) + x, y)),
+ MatchesOneOf(floormod(x + floormod(z, y), y), floormod(floormod(z, y)
+ x, y)),
ZeroWithTypeLike(x), CanProveEqual(floormod(x.Eval() + z.Eval(),
y.Eval()), 0));
// x = ay + b, then (ay + b - (ay + b) % +-y) % y -> (b - b % +-y) % y -> 0
TVM_TRY_REWRITE_IF(
- matches_one_of(floormod(x - floormod(x, z), y), floormod(floormod(x,
z) - x, y)),
+ MatchesOneOf(floormod(x - floormod(x, z), y), floormod(floormod(x, z)
- x, y)),
ZeroWithTypeLike(x),
CanProveEqual(y.Eval() - z.Eval(), 0) || CanProveEqual(y.Eval() +
z.Eval(), 0));
@@ -1299,19 +1298,19 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::MinNode* op,
// DivMod rules
// NOTE: trucdiv(x, y) >= floordiv(x, y)
TVM_TRY_REWRITE_IF(
- matches_one_of(min(truncdiv(x + c1, c2) * c2, x), min(x, truncdiv(x +
c1, c2) * c2),
- min(floordiv(x + c1, c2) * c2, x), min(x, floordiv(x +
c1, c2) * c2)),
+ MatchesOneOf(min(truncdiv(x + c1, c2) * c2, x), min(x, truncdiv(x +
c1, c2) * c2),
+ min(floordiv(x + c1, c2) * c2, x), min(x, floordiv(x +
c1, c2) * c2)),
x, c2.Eval()->value > 0 && c1.Eval()->value + 1 == c2.Eval()->value);
- TVM_TRY_REWRITE_IF(matches_one_of(min(truncdiv(x + c1, c2) * c2, max(x,
c2)),
- min(max(x, c2), truncdiv(x + c1, c2) *
c2),
- min(floordiv(x + c1, c2) * c2, max(x,
c2)),
- min(max(x, c2), floordiv(x + c1, c2) *
c2)),
+ TVM_TRY_REWRITE_IF(MatchesOneOf(min(truncdiv(x + c1, c2) * c2, max(x, c2)),
+ min(max(x, c2), truncdiv(x + c1, c2) * c2),
+ min(floordiv(x + c1, c2) * c2, max(x, c2)),
+ min(max(x, c2), floordiv(x + c1, c2) *
c2)),
max(x, c2),
c2.Eval()->value > 0 && c1.Eval()->value + 1 ==
c2.Eval()->value &&
CanProveGreaterEqual(x.Eval(), 1));
- TVM_TRY_REWRITE_IF(matches_one_of(min(x, floordiv(x, c2) * c2),
min(floordiv(x, c2) * c2, x)),
+ TVM_TRY_REWRITE_IF(MatchesOneOf(min(x, floordiv(x, c2) * c2),
min(floordiv(x, c2) * c2, x)),
floordiv(x, c2) * c2, c2.Eval()->value > 0);
TVM_TRY_REWRITE((PMatchesOneOf{
@@ -1911,8 +1910,8 @@ PrimExpr
RewriteSimplifier::Impl::ApplyRewriteRules(prim::LT ret, InplaceMode in
// clang-format on
- TVM_TRY_RECURSIVE_REWRITE(matches_one_of(c1 < x + c2, c1 - x < c2), c1 -
c2 < x);
- TVM_TRY_RECURSIVE_REWRITE(matches_one_of(c1 < c2 - x, x + c1 < c2), x < c2
- c1);
+ TVM_TRY_RECURSIVE_REWRITE(MatchesOneOf(c1 < x + c2, c1 - x < c2), c1 - c2
< x);
+ TVM_TRY_RECURSIVE_REWRITE(MatchesOneOf(c1 < c2 - x, x + c1 < c2), x < c2 -
c1);
TVM_TRY_RECURSIVE_REWRITE(c1 < x - c2, c1 + c2 < x);
TVM_TRY_RECURSIVE_REWRITE(x - c2 < c1, x < c1 + c2);
@@ -2040,10 +2039,10 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::AndNode* op,
cfalse, c2.Eval()->value > c1.Eval()->value);
TVM_TRY_REWRITE((x == c1) && (x == c2), (x == c1) && (c1 == c2));
- TVM_TRY_REWRITE(matches_one_of(x == c1 && x != c2, x != c2 && x == c1), x ==
c1 && c1 != c2);
+ TVM_TRY_REWRITE(MatchesOneOf(x == c1 && x != c2, x != c2 && x == c1), x ==
c1 && c1 != c2);
- TVM_TRY_RECURSIVE_REWRITE(matches_one_of(floordiv(x, c2) == c1 &&
floormod(x, c2) == c3,
- floormod(x, c2) == c3 &&
floordiv(x, c2) == c1),
+ TVM_TRY_RECURSIVE_REWRITE(MatchesOneOf(floordiv(x, c2) == c1 && floormod(x,
c2) == c3,
+ floormod(x, c2) == c3 && floordiv(x,
c2) == c1),
x == c1 * c2 + c3);
TVM_TRY_RECURSIVE_REWRITE_IF((PMatchesOneOf{
@@ -2079,18 +2078,18 @@ UnchangedOr<PrimExpr>
RewriteSimplifier::Impl::Mutate_(const prim::AndNode* op,
(((c1.Eval()->value + 1) % c2.Eval()->value) + c2.Eval()->value) %
c2.Eval()->value >
c3.Eval()->value);
- TVM_TRY_RECURSIVE_REWRITE(matches_one_of(floordiv(x, c2) == c1 &&
floormod(x, c2) < c3,
- floormod(x, c2) < c3 && floordiv(x,
c2) == c1),
+ TVM_TRY_RECURSIVE_REWRITE(MatchesOneOf(floordiv(x, c2) == c1 && floormod(x,
c2) < c3,
+ floormod(x, c2) < c3 && floordiv(x,
c2) == c1),
c1 * c2 <= x && x < c1 * c2 + c3);
- TVM_TRY_RECURSIVE_REWRITE(matches_one_of(floordiv(x, c2) == c1 &&
floormod(x, c2) <= c3,
- floormod(x, c2) <= c3 &&
floordiv(x, c2) == c1),
+ TVM_TRY_RECURSIVE_REWRITE(MatchesOneOf(floordiv(x, c2) == c1 && floormod(x,
c2) <= c3,
+ floormod(x, c2) <= c3 && floordiv(x,
c2) == c1),
c1 * c2 <= x && x <= c1 * c2 + c3);
- TVM_TRY_RECURSIVE_REWRITE(matches_one_of(floordiv(x, c2) == c1 && c3 <=
floormod(x, c2),
- c3 <= floormod(x, c2) &&
floordiv(x, c2) == c1),
+ TVM_TRY_RECURSIVE_REWRITE(MatchesOneOf(floordiv(x, c2) == c1 && c3 <=
floormod(x, c2),
+ c3 <= floormod(x, c2) && floordiv(x,
c2) == c1),
c1 * c2 + c3 <= x && x < (c1 + 1) * c2);
- TVM_TRY_RECURSIVE_REWRITE(matches_one_of(floordiv(x, c2) == c1 && c3 <
floormod(x, c2),
- c3 < floormod(x, c2) && floordiv(x,
c2) == c1),
+ TVM_TRY_RECURSIVE_REWRITE(MatchesOneOf(floordiv(x, c2) == c1 && c3 <
floormod(x, c2),
+ c3 < floormod(x, c2) && floordiv(x,
c2) == c1),
c1 * c2 + c3 < x && x < (c1 + 1) * c2);
TVM_TRY_RECURSIVE_REWRITE(x && (y && z), (x && y) && z);
diff --git a/src/sym/rewrite_simplify.h b/src/sym/rewrite_simplify.h
index a374f918..c54d25a9 100644
--- a/src/sym/rewrite_simplify.h
+++ b/src/sym/rewrite_simplify.h
@@ -27,6 +27,7 @@
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ir/cow.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/sym/analyzer.h>
#include <algorithm>
@@ -34,7 +35,6 @@
#include <vector>
#include "const_fold.h"
-#include "pattern_match.h"
#include "simplify_base.h"
namespace tvm {
diff --git a/src/sym/detect_linear_equation.cc
b/src/tirx/analysis/linear_analysis.cc
similarity index 96%
rename from src/sym/detect_linear_equation.cc
rename to src/tirx/analysis/linear_analysis.cc
index 2199de96..08c3d0a4 100644
--- a/src/sym/detect_linear_equation.cc
+++ b/src/tirx/analysis/linear_analysis.cc
@@ -18,7 +18,7 @@
*/
/*!
- * \file detect_linear_equation.cc
+ * \file linear_analysis.cc
* \brief Utility to detect patterns in the expression.
*/
#include <tvm/ffi/extra/structural_visit.h>
@@ -28,12 +28,12 @@
#include <tvm/ir/prim/expr.h>
#include <tvm/ir/prim/op.h>
#include <tvm/sym/analyzer.h>
-#include <tvm/sym/pattern.h>
+#include <tvm/tirx/analysis.h>
#include <unordered_set>
namespace tvm {
-namespace sym {
+namespace tirx {
using namespace tvm::prim;
// Linear equation, the components can be undefined.
@@ -226,7 +226,7 @@ bool DetectClipBound(const PrimExpr& cond,
return false;
}
LinearEqEntry ret;
- Analyzer analyzer;
+ sym::Analyzer analyzer;
if (!LinearEqDetector(var.value()).Detect(canonical, &ret)) return false;
ret.coeff = analyzer->Simplify(ret.coeff.value());
IntervalEntry& p = bmap->at(var.value().get());
@@ -281,7 +281,7 @@ void SplitCommExpr(const PrimExpr& e,
std::vector<PrimExpr>* ret) {
ffi::Array<ffi::Optional<PrimExpr>> DetectClipBound(const PrimExpr& e,
const ffi::Array<PrimVar>&
vars) {
std::vector<PrimExpr> splits;
- Analyzer analyzer;
+ sym::Analyzer analyzer;
SplitCommExpr<prim::AndNode>(analyzer->Simplify(e), &splits);
std::unordered_map<const VarNode*, IntervalEntry> rmap;
for (PrimVar v : vars) {
@@ -308,10 +308,10 @@ ffi::Array<ffi::Optional<PrimExpr>> DetectClipBound(const
PrimExpr& e,
TVM_FFI_STATIC_INIT_BLOCK() {
namespace refl = tvm::ffi::reflection;
refl::GlobalDef()
- .def("sym.DetectLinearEquation", DetectLinearEquation)
- .def("sym.DetectClipBound", [](const PrimExpr& e, const
ffi::Array<PrimVar>& vars) {
+ .def("tirx.analysis.DetectLinearEquation", DetectLinearEquation)
+ .def("tirx.analysis.DetectClipBound", [](const PrimExpr& e, const
ffi::Array<PrimVar>& vars) {
return DetectClipBound(e, vars);
});
}
-} // namespace sym
+} // namespace tirx
} // namespace tvm
diff --git a/src/tirx/ir/tensor.cc b/src/tirx/ir/tensor.cc
index a21d8917..00d08bfe 100644
--- a/src/tirx/ir/tensor.cc
+++ b/src/tirx/ir/tensor.cc
@@ -25,6 +25,7 @@
#include <tvm/ir/expr.h>
#include <tvm/ir/prim/expr.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/sym/analyzer.h>
#include <tvm/tirx/analysis.h>
#include <tvm/tirx/expr.h>
@@ -36,8 +37,6 @@
#include <stack>
#include <utility>
-#include "../../sym/pattern_match.h"
-
namespace tvm {
TensorRegion TensorRegion::FromTensorLoad(TensorLoad value) {
@@ -332,7 +331,7 @@ inline PrimExpr MergeMulMod(sym::AnalyzerObj* analyzer,
const PrimExpr& base) {
// The elements in the Mod will be used to match against the elements in Mul.
// The result will then be split and pushed back to these two lists.
PrimExpr simplified_base = base;
- sym::PVar<PrimExpr> x, y;
+ tvm::PVar<PrimExpr> x, y;
if ((floordiv(x, y) * y + floormod(x, y)).Match(simplified_base)) {
simplified_base = x.Eval();
}
diff --git a/src/tirx/op/math.cc b/src/tirx/op/math.cc
index 5f03e3d4..07b9999c 100644
--- a/src/tirx/op/math.cc
+++ b/src/tirx/op/math.cc
@@ -30,7 +30,7 @@ namespace tvm {
namespace tirx {
using namespace prim;
-using namespace prim::detail;
+using namespace prim::details;
PrimExpr logaddexp(PrimExpr a, PrimExpr b, Location loc) {
TVM_FFI_ICHECK(a.ty().MatchesCode(DLDataTypeCode::kDLFloat)) << a;
diff --git a/src/tirx/tile/lower.cc b/src/tirx/tile/lower.cc
index 06395251..05219ae0 100644
--- a/src/tirx/tile/lower.cc
+++ b/src/tirx/tile/lower.cc
@@ -30,7 +30,6 @@
#include <tvm/ir/prim/op.h>
#include <tvm/runtime/logging.h>
#include <tvm/sym/analyzer.h>
-#include <tvm/sym/pattern.h>
#include <tvm/target/target.h>
#include <tvm/tirx/function.h>
#include <tvm/tirx/op/annotation.h>
diff --git a/src/tirx/transform/lower_intrin.cc
b/src/tirx/transform/lower_intrin.cc
index 73f4dc24..79e3b3f5 100644
--- a/src/tirx/transform/lower_intrin.cc
+++ b/src/tirx/transform/lower_intrin.cc
@@ -28,6 +28,7 @@
#include <tvm/ir/op.h>
#include <tvm/ir/prim/expr.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/runtime/logging.h>
#include <tvm/target/target.h>
#include <tvm/tirx/expr.h>
@@ -38,8 +39,6 @@
#include <limits>
#include <unordered_set>
-#include "../../sym/pattern_match.h"
-
namespace tvm {
namespace tirx {
using namespace tvm::prim;
@@ -249,7 +248,6 @@ class IntrinInjecter : public StmtExprMutatorWithAnalyzer {
}
UnchangedOr<PrimExpr> Mutate_(const prim::MaxNode* op, InplaceMode
inplace_mode) final {
- using namespace sym;
PVar<PrimExpr> x, y;
PVar<IntImm> c;
auto e = ffi::GetRef<PrimExpr>(op);
@@ -262,7 +260,6 @@ class IntrinInjecter : public StmtExprMutatorWithAnalyzer {
}
UnchangedOr<PrimExpr> Mutate_(const prim::EQNode* op, InplaceMode
inplace_mode) final {
- using namespace sym;
PVar<PrimExpr> x, y;
auto e = ffi::GetRef<PrimExpr>(op);
if ((floormod(x, y) == 0).Match(e)) {
@@ -273,7 +270,6 @@ class IntrinInjecter : public StmtExprMutatorWithAnalyzer {
}
UnchangedOr<PrimExpr> Mutate_(const prim::NENode* op, InplaceMode
inplace_mode) final {
- using namespace sym;
PVar<PrimExpr> x, y;
auto e = ffi::GetRef<PrimExpr>(op);
if ((floormod(x, y) != 0).Match(e)) {
diff --git a/src/tirx/transform/remove_no_op.cc
b/src/tirx/transform/remove_no_op.cc
index 3fb1d69f..1ee38d43 100644
--- a/src/tirx/transform/remove_no_op.cc
+++ b/src/tirx/transform/remove_no_op.cc
@@ -33,7 +33,6 @@
#include <tvm/tirx/stmt_functor_with_analyzer.h>
#include <tvm/tirx/transform.h>
-#include "../../sym/const_fold.h"
#include "ir_utils.h"
namespace tvm {
@@ -120,7 +119,7 @@ class NoOpRemover : public StmtExprMutatorWithAnalyzer {
UnchangedOr<Stmt> Mutate_(const ForNode* op, InplaceMode inplace_mode) final
{
auto extent_range =
sym::EvalSet(Range::GetExtentFromBeginEnd(op->begin, op->end),
var_range_map_);
- if (!sym::is_neg_inf(extent_range.max()) &&
!sym::is_pos_inf(extent_range.max()) &&
+ if (!prim::is_neg_inf(extent_range.max()) &&
!prim::is_pos_inf(extent_range.max()) &&
analyzer_->CanProve(extent_range.max() <= 0)) {
return Evaluate(0);
}
diff --git a/src/tirx/transform/renormalize_split_pattern.cc
b/src/tirx/transform/renormalize_split_pattern.cc
index 0493c783..b52bab7b 100644
--- a/src/tirx/transform/renormalize_split_pattern.cc
+++ b/src/tirx/transform/renormalize_split_pattern.cc
@@ -24,11 +24,12 @@
#include <tvm/ffi/function.h>
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ir/prim/op.h>
+#include <tvm/ir/prim/pattern_match.h>
#include <tvm/tirx/stmt.h>
#include <tvm/tirx/stmt_functor_with_analyzer.h>
#include <tvm/tirx/transform.h>
-#include "../../sym/pattern_match.h"
+#include "../../sym/int_operator.h"
namespace tvm {
namespace tirx {
diff --git a/tests/cpp/sym/pattern_match_test.cc
b/tests/cpp/ir/pattern_match_test.cc
similarity index 94%
rename from tests/cpp/sym/pattern_match_test.cc
rename to tests/cpp/ir/pattern_match_test.cc
index 2683c398..24477477 100644
--- a/tests/cpp/sym/pattern_match_test.cc
+++ b/tests/cpp/ir/pattern_match_test.cc
@@ -17,19 +17,17 @@
* under the License.
*/
-#include "../../../src/sym/pattern_match.h"
-
#include <gtest/gtest.h>
#include <tvm/ir/prim/expr.h>
+#include <tvm/ir/prim/pattern_match.h>
TEST(Pattern, Basic) {
using namespace tvm;
- using namespace tvm::sym;
tvm::PrimVar x("x"), y("y"), z("z");
PrimExpr scalable_lanes = prim::Mul(Call(PrimType::Int(32),
prim::vscale_op(), {}), 4);
- sym::PVar<PrimExpr> px, py, pz;
- sym::PVar<DLDataType> pt;
- sym::PVar<PrimExpr> planes;
+ tvm::PVar<PrimExpr> px, py, pz;
+ tvm::PVar<DLDataType> pt;
+ tvm::PVar<PrimExpr> planes;
// arithmetics
auto r = 1 + (y + 1);
@@ -130,8 +128,8 @@ TEST(Pattern, Basic) {
TEST(Pattern, IntImm) {
using namespace tvm;
PrimVar tx("tx"), ty("ty");
- sym::PVar<IntImm> c;
- sym::PVar<Var> v;
+ tvm::PVar<IntImm> c;
+ tvm::PVar<Var> v;
{
// We can match integer and Var, both of which are
// special case container of Expr
@@ -148,7 +146,7 @@ TEST(Pattern, IntImm) {
TEST(Pattern, MatchWithType) {
using namespace tvm;
// match expr with specified dtype
- sym::PVarWithDataType<PrimExpr, sym::PConst<DLDataType>>
pat(DLDataType{kDLFloat, 32, 1});
+ tvm::PVarWithDataType<PrimExpr, tvm::PConst<DLDataType>>
pat(DLDataType{kDLFloat, 32, 1});
PrimVar x("x", PrimType::Float(32));
PrimVar y("y", PrimType::Float(32));
PrimVar x_int("x", PrimType::Int(32));
@@ -157,8 +155,8 @@ TEST(Pattern, MatchWithType) {
TVM_FFI_ICHECK(!pat.Match(x_int + y_int * 2));
// match vectorized expr with specified element dtype
- sym::PVecDataType vec_ty(DLDataType{kDLFloat, 32, 1});
- sym::PVarWithDataType<PrimExpr, sym::PVecDataType> vpat(vec_ty);
+ tvm::PVecDataType vec_ty(DLDataType{kDLFloat, 32, 1});
+ tvm::PVarWithDataType<PrimExpr, tvm::PVecDataType> vpat(vec_ty);
PrimVar vx("x", PrimType::Float(32, 8));
PrimVar vy("y", PrimType::Float(32, 8));
PrimVar vx_int("x", PrimType::Int(32, 8));
diff --git a/tests/cpp/sym/domain_map_test.cc b/tests/cpp/sym/domain_map_test.cc
index bf2c8ec4..8bd2b7cf 100644
--- a/tests/cpp/sym/domain_map_test.cc
+++ b/tests/cpp/sym/domain_map_test.cc
@@ -20,7 +20,6 @@
#include <gtest/gtest.h>
#include <tvm/ir/prim/op.h>
#include <tvm/sym/analyzer.h>
-#include <tvm/sym/bound.h>
#include <tvm/sym/int_set.h>
namespace tvm {
diff --git a/tests/python/sym/test_detect_clip_bound.py
b/tests/python/tirx/analysis/test_detect_clip_bound.py
similarity index 78%
rename from tests/python/sym/test_detect_clip_bound.py
rename to tests/python/tirx/analysis/test_detect_clip_bound.py
index 55143e84..6a2641b5 100644
--- a/tests/python/sym/test_detect_clip_bound.py
+++ b/tests/python/tirx/analysis/test_detect_clip_bound.py
@@ -22,19 +22,23 @@ def test_basic():
a = tvm_tirx.tirx.Var("a", "int32")
b = tvm_tirx.tirx.Var("b", "int32")
c = tvm_tirx.tirx.Var("c", "int32")
- m = tvm_tirx.sym.detect_clip_bound(tvm_tirx.tirx.all(a * 1 < b * 6, a - 1
> 0), [a])
+ m = tvm_tirx.tirx.analysis.detect_clip_bound(tvm_tirx.tirx.all(a * 1 < b *
6, a - 1 > 0), [a])
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[1], b * 6 - 1)
assert m[0].value == 2
- m = tvm_tirx.sym.detect_clip_bound(tvm_tirx.tirx.all(a * 1 < b * 6, a - 1
> 0), [a, b])
+ m = tvm_tirx.tirx.analysis.detect_clip_bound(
+ tvm_tirx.tirx.all(a * 1 < b * 6, a - 1 > 0), [a, b]
+ )
assert len(m) == 0
- m = tvm_tirx.sym.detect_clip_bound(tvm_tirx.tirx.all(a + 10 * c <= 20, b -
1 > 0), [a, b])
+ m = tvm_tirx.tirx.analysis.detect_clip_bound(
+ tvm_tirx.tirx.all(a + 10 * c <= 20, b - 1 > 0), [a, b]
+ )
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[1], 20 - 10 * c)
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[2], 2)
- m = tvm_tirx.sym.detect_clip_bound(
+ m = tvm_tirx.tirx.analysis.detect_clip_bound(
tvm_tirx.tirx.all(tvm_tirx.tirx.Not(a * 1 > b * 6), a - 1 > 0), [a]
)
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[1], b * 6)
- m = tvm_tirx.sym.detect_clip_bound(
+ m = tvm_tirx.tirx.analysis.detect_clip_bound(
tvm_tirx.tirx.all(tvm_tirx.tirx.Min(a, b) > 3, a - 10 < 0), [a, b]
)
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[0], 4)
@@ -45,10 +49,10 @@ def test_basic():
def test_trivial_eq():
a = tvm_tirx.tirx.Var("a", "int32")
b = tvm_tirx.tirx.Var("b", "int32")
- m = tvm_tirx.sym.detect_clip_bound(b == 3, [a, b])
+ m = tvm_tirx.tirx.analysis.detect_clip_bound(b == 3, [a, b])
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[2], 3)
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[3], 3)
- m = tvm_tirx.sym.detect_clip_bound(tvm_tirx.tirx.all(a == 4, b == 3), [a,
b])
+ m = tvm_tirx.tirx.analysis.detect_clip_bound(tvm_tirx.tirx.all(a == 4, b
== 3), [a, b])
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[0], 4)
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[1], 4)
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[2], 3)
diff --git a/tests/python/sym/test_detect_linear_equation.py
b/tests/python/tirx/analysis/test_detect_linear_equation.py
similarity index 65%
rename from tests/python/sym/test_detect_linear_equation.py
rename to tests/python/tirx/analysis/test_detect_linear_equation.py
index 151a8b93..d4706940 100644
--- a/tests/python/sym/test_detect_linear_equation.py
+++ b/tests/python/tirx/analysis/test_detect_linear_equation.py
@@ -21,58 +21,60 @@ import tvm_tirx.testing
def test_basic():
a = tvm_tirx.tirx.Var("a", "int32")
b = tvm_tirx.tirx.Var("b", "int32")
- m = tvm_tirx.sym.detect_linear_equation(a * 4 + b * 6 + 7, [a])
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(a * 4 + b * 6 + 7, [a])
assert m[0].value == 4
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[1], b * 6 + 7)
- m = tvm_tirx.sym.detect_linear_equation(a * 4 * (a + 1) + b * 6 + 7, [a])
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(a * 4 * (a + 1) + b * 6
+ 7, [a])
assert len(m) == 0
- m = tvm_tirx.sym.detect_linear_equation(a * 4 + (a + 1) + b * 6 + 7, [a])
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(a * 4 + (a + 1) + b * 6
+ 7, [a])
assert m[0].value == 5
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[1], b * 6 + 7 + 1)
- m = tvm_tirx.sym.detect_linear_equation(a * b + 7, [a])
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(a * b + 7, [a])
assert m[0] == b
- m = tvm_tirx.sym.detect_linear_equation(b * 7, [a])
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(b * 7, [a])
assert m[0].value == 0
- m = tvm_tirx.sym.detect_linear_equation(b * 7, [])
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(b * 7, [])
assert len(m) == 1
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[0], b * 7)
c = tvm_tirx.tirx.Var("c", "uint32")
- m = tvm_tirx.sym.detect_linear_equation(128 - c, [c])
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(128 - c, [c])
assert m[0].value == -1
def test_multivariate():
v = [tvm_tirx.tirx.Var(f"v{i}", "int32") for i in range(4)]
b = tvm_tirx.tirx.Var("b", "int32")
- m = tvm_tirx.sym.detect_linear_equation(v[0] * (b + 4) + v[0] + v[1] * 8,
v)
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(v[0] * (b + 4) + v[0] +
v[1] * 8, v)
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[0], b + 5)
assert m[1].value == 8
- m = tvm_tirx.sym.detect_linear_equation(v[0] * (b + 4) + v[0] + v[1] * 8 *
v[2], v)
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(v[0] * (b + 4) + v[0] +
v[1] * 8 * v[2], v)
assert len(m) == 0
- m = tvm_tirx.sym.detect_linear_equation(v[0] * (b + 4) + v[0] + v[1] * 8 *
v[1] + v[3], v)
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(
+ v[0] * (b + 4) + v[0] + v[1] * 8 * v[1] + v[3], v
+ )
assert len(m) == 0
- m = tvm_tirx.sym.detect_linear_equation(((v[0] * b + v[1]) * 8 + v[2] + 1)
* 2, v)
+ m = tvm_tirx.tirx.analysis.detect_linear_equation(((v[0] * b + v[1]) * 8 +
v[2] + 1) * 2, v)
assert m[1].value == 16
assert m[2].value == 2
assert m[len(m) - 1].value == 2
- m = tvm_tirx.sym.detect_linear_equation((v[0] - v[1]), [v[2]])
+ m = tvm_tirx.tirx.analysis.detect_linear_equation((v[0] - v[1]), [v[2]])
assert m[0].value == 0
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[1], v[0] - v[1])
- m = tvm_tirx.sym.detect_linear_equation((v[0] - v[1]), [])
+ m = tvm_tirx.tirx.analysis.detect_linear_equation((v[0] - v[1]), [])
assert len(m) == 1
assert tvm_tirx.sym.Analyzer().can_prove_equal(m[0], v[0] - v[1])