Files
wehub-resource-sync 26446540fa
Lint / lint (push) Waiting to run
CI / MacOS (push) Waiting to run
CI / Windows (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:25 +08:00

340 lines
12 KiB
C++

/*
* 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/arith/int_set.h
* \brief Integer set
*/
#ifndef TVM_ARITH_INT_SET_H_
#define TVM_ARITH_INT_SET_H_
#include <tvm/ir/expr.h>
#include <tvm/tirx/expr.h>
#include <unordered_map>
namespace tvm {
namespace arith {
using tirx::IterVar;
using tirx::Var;
using tirx::VarNode;
class AnalyzerObj;
class Analyzer;
//-----------------------------------------------
// Integer set data structure.
//
// This is a API build on top of the base
// integer analysis API to provide set analysis.
//------------------------------------------------
/*!
* \brief Sign type of an integer expression.
*/
enum SignType { kPositive, kNegative, kZero, kUnknown };
/*!
* \brief Base class of all Integer set containers.
* represent a set of integers in one dimension.
* \sa IntSet
*/
class IntSetNode : public ffi::Object {
public:
TVM_FFI_DECLARE_OBJECT_INFO("ir.IntSet", IntSetNode, ffi::Object);
};
/*!
* \brief Managed reference to IntSetNode.
* \sa IntSetNode
*/
class IntSet : public ffi::ObjectRef {
public:
/*!
* \brief Find a range that covers the region.
* \param max_range The range to be covered.
* \return The covering range.
*/
Range CoverRange(Range max_range) const;
/*! \return Lower bound of the set */
PrimExpr min() const;
/*! \return upper bound of the set */
PrimExpr max() const;
/*! \return The sign of the elements in the integer set */
SignType GetSignType() const;
/*! \return Whether the set represent nothing */
bool IsNothing() const;
/*! \return Whether the set represent everything */
bool IsEverything() const;
/*! \return Whether the set is a single point */
bool IsSinglePoint() const;
/*!
* \brief Check if we can prove it is a single point.
*
* Unlike IsSinglePoint, which only checks ptr equality
* this function will invoke analyzer to do stonger proofs
* but also takes longer time.
*
* Use this function in some of the primitives but do not
* use it in the inner loop of simplification.
*
* \param ana Analyzer used in the proof.
* \return Whether we can prove it is a single point
*/
bool CanProveSinglePoint(const Analyzer& ana) const;
// TODO(tvm-team): update all CanProve to explicitly take
// analyzer to encourage more analyzer reuse
/*! \return Whether the set is proved to be bigger than 0 */
bool CanProvePositive() const;
/*! \return Whether the set is proved to be smaller than 0 */
bool CanProveNegative() const;
/*! \return Whether the set is proved to be smaller than or equal to 0 */
bool CanProveNonPositive() const;
/*! \return Whether the set is proved to be larger than or equal to 0 */
bool CanProveNonNegative() const;
/*! \return Whether the set has upper bound. */
bool HasUpperBound() const;
/*! \return Whether the set has lower bound. */
bool HasLowerBound() const;
/*!
* \brief The single point value, call only if IsSinglePoint is true
* \return The point value.
*/
PrimExpr PointValue() const;
/*!
* \brief Try to match IntSet with range r.
*
* \note It is guanrateed that IntSet::FromRange(r).MatchRange(r) == true
* \return true if we can prove they are the same.
*/
bool MatchRange(const tvm::Range& r) const;
/*! \return The set contains nothing */
static IntSet Nothing();
/*! \return The set contains everything */
static IntSet Everything();
/*!
* \brief construct a point set.
* \param point The point in the set.
* \return construct a single point set
*/
static IntSet SinglePoint(PrimExpr point);
/*!
* \brief construct a integer set from vector expression.
* \param vec The vector expression, can also be single point.
* \return The result set containing the indices in the vector.
*/
static IntSet Vector(PrimExpr vec);
/*!
* \brief Construct a set representing a range [min, min + extent).
* \param min The minimum of the range range
* \param extent The extent of the range.
* \return The constructed set.
*/
static IntSet FromMinExtent(PrimExpr min, PrimExpr extent);
/*!
* \brief Construct a set representing a range.
* \param r The range
* \return The constructed set.
*/
static IntSet FromRange(tvm::Range r);
/*!
* \brief Construct a set representing a interval.
* \param min The minimum value of the interval.
* \param max The maximum value of the interval.
* \return The constructed set.
*/
static IntSet Interval(PrimExpr min, PrimExpr max);
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(IntSet, ffi::ObjectRef, IntSetNode);
};
//-----------------------------------------------
// Integer set legacy API.
//------------------------------------------------
/*!
* \brief Convert std::unordered_map<const VarNode*, IntSet> to ffi::Map<Var, IntSet>
*
* \param dom_map The domain map to convert.
* \return The converted map.
*/
ffi::Map<Var, IntSet> ConvertDomMap(const std::unordered_map<const VarNode*, IntSet>& dom_map);
/*!
* \brief Find an symbolic integer set that contains all possible values of
* e given the domain of each iteration variables.
*
* \param e The expression to be evaluated.
* \param dom_map The domain of each variable.
* \return An integer set that can cover all the possible values of e.
*/
IntSet EvalSet(PrimExpr e, const ffi::Map<IterVar, IntSet>& dom_map);
/*!
* \brief Find an symbolic integer set that contains all possible values of
* e given the domain of each variables.
*
* \param e The expression to be evaluated.
* \param dom_map The domain of each variable.
* \return An integer set that can cover all the possible values of e.
*/
IntSet EvalSet(PrimExpr e, const ffi::Map<Var, IntSet>& dom_map);
/*!
* \brief Same as EvalSet, but takes unordered_map
*
* \param e The expression to be evaluated.
* \param dom_map The domain of each variable.
* \return An integer set that can cover all the possible values of e.
*/
IntSet EvalSet(PrimExpr e, const std::unordered_map<const tirx::VarNode*, IntSet>& dom_map);
/*!
* \brief Find an symbolic integer set that contains is union over
* all the possible conditional values in dom_map.
*
* \param r The initial range.
* \param dom_map The domain of each variable.
* \return An integer set that can cover all the possible values.
*/
IntSet EvalSet(Range r, const ffi::Map<IterVar, IntSet>& dom_map);
/*!
* \brief Find an symbolic integer set that contains is union over
* all the possible conditional values in dom_map.
*
* \param s The initial set.
* \param dom_map The domain of each variable.
* \return An integer set that can cover all the possible values.
*/
IntSet EvalSet(IntSet s, const std::unordered_map<const VarNode*, IntSet>& dom_map);
/*!
* \brief Same as EvalSet, but takes unordered_map
*
* \param r The range to be evaluated.
* \param dom_map The domain of each variable.
* \return An integer set that can cover all the possible values of e.
*/
IntSet EvalSet(Range r, const std::unordered_map<const VarNode*, IntSet>& dom_map);
/*!
* \brief Same as EvalSet, but takes ffi::Array<Range>
*
* \param region The range to be evaluated.
* \param dom_map The domain of each variable.
* \return An array of integer sets that can cover all the possible values.
*/
ffi::Array<IntSet> EvalSet(const ffi::Array<Range>& region, const ffi::Map<Var, IntSet>& dom_map);
/*! \brief Map from Expr to IntSet */
using ExprIntSetMap = std::unordered_map<PrimExpr, IntSet, ffi::ObjectPtrHash, ffi::ObjectPtrEqual>;
/*!
* \brief Find the integer set of every sub-expression, given the
* domain of each iteration variables.
*
* \param e The expression to be evaluated.
* \param dom_map The domain of each variable.
* \return the map from the expression to its possible value.
*/
ExprIntSetMap EvalSetForEachSubExpr(PrimExpr e,
const std::unordered_map<const VarNode*, IntSet>& dom_map);
/*!
* \brief Create a union set of all sets, possibly relaxed
* \param sets The sets to be combined
* \return the set after union
*/
IntSet Union(const ffi::Array<IntSet>& sets);
/*!
* \brief The union of N-dimensional integer sets
* \param nd_int_sets A list of N-dimensional integer sets
* \return An N-dimensional integer set as the result of union
*/
ffi::Array<IntSet> UnionRegion(const ffi::Array<ffi::Array<IntSet>>& nd_int_sets);
/*!
* \brief Create a lower-bound of union set, where some of the segments may be dropped
* \param sets The sets to be combined
* \return the set after union
*/
IntSet UnionLowerBound(const ffi::Array<IntSet>& sets);
/*!
* \brief The union of N-dimensional integer sets
* \param nd_int_sets A list of N-dimensional integer sets
* \return An N-dimensional integer set as the result of union
*/
ffi::Array<IntSet> UnionRegionLowerBound(const ffi::Array<ffi::Array<IntSet>>& nd_int_sets);
/*!
* \brief Create an intersected set of all sets
* \param sets The sets to be intersected
* \return the set after intersected
*/
IntSet Intersect(const ffi::Array<IntSet>& sets);
/*!
* \brief Converts the Ranges to IntSets
* \param var_dom The ranges of variables
* \return The integer sets of the variables
*/
ffi::Map<Var, arith::IntSet> AsIntSet(const ffi::Map<Var, Range>& var_dom);
/*!
* \brief Analyze the region with affine map, given the domain of variables and their predicate.
* The result should be strict, i.e. no region is discarded or relaxed.
* \param region The region to be analyzed
* \param var_dom The ranges of the variables
* \param predicate The predicate for the affine map
* \param analyzer The analyzer used
* \return std::nullopt if the detection fails, or an array of arith::IntSet as the result of
* analysis
*/
TVM_DLL ffi::Optional<ffi::Array<IntSet>> EstimateRegionStrictBound(
const ffi::Array<Range>& region, const ffi::Map<Var, Range>& var_dom, const PrimExpr& predicate,
const arith::Analyzer& analyzer);
/*!
* \brief Analyze the region with affine map, given the domain of variables and their predicate.
* Some subregion may be discarded during the lower-bound analysis.
* \param region The region to be analyzed
* \param var_dom The ranges of the variables
* \param predicate The predicate for the affine map
* \param analyzer The analyzer used
* \return std::nullopt if the detection fails, or an array of arith::IntSet as the result of
* analysis
*/
TVM_DLL ffi::Optional<ffi::Array<IntSet>> EstimateRegionLowerBound(
const ffi::Array<Range>& region, const ffi::Map<Var, Range>& var_dom, const PrimExpr& predicate,
const arith::Analyzer& analyzer);
/*!
* \brief Analyze the region with affine map, given the domain of variables and their predicate
* Relaxation of the region may be used in upper-bound analysis, i.e. some extra region may be added
* to the result.
* \param region The region to be analyzed
* \param var_dom The ranges of the variables
* \param predicate The predicate for the affine map
* \param analyzer The analyzer used
* \return an array of arith::IntSet as the result of analysis
*/
TVM_DLL ffi::Array<IntSet> EstimateRegionUpperBound(const ffi::Array<Range>& region,
const ffi::Map<Var, Range>& var_dom,
const PrimExpr& predicate,
const arith::Analyzer& analyzer);
} // namespace arith
} // namespace tvm
#endif // TVM_ARITH_INT_SET_H_