#ifndef HALIDE_DEFINITION_H
#define HALIDE_DEFINITION_H
/** \file
* Defines the internal representation of a halide function's definition and related classes
*/
#include "Expr.h"
#include "IntrusivePtr.h"
#include "Schedule.h"
#include "Reduction.h"
#include <map>
namespace Halide {
namespace Internal {
struct DefinitionContents;
struct FunctionContents;
}
namespace Internal {
class IRVisitor;
class IRMutator;
struct Specialization;
/** A Function definition which can either represent a init or an update
* definition. A function may have different definitions due to specialization,
* which are stored in 'specializations' (Not possible from the front-end, but
* some scheduling directives may potentially cause this divergence to occur).
* Although init definition may have multiple values (RHS) per specialization, it
* must have the same LHS (i.e. same pure dimension variables). The update
* definition, on the other hand, may have different LHS/RHS per specialization.
* Note that, while the Expr in LHS/RHS may be different across specializations,
* they must have the same number of dimensions and the same pure dimensions.
*/
class Definition {
IntrusivePtr<DefinitionContents> contents;
public:
/** Construct a Definition from an existing DefinitionContents pointer. Must be non-null */
EXPORT explicit Definition(const IntrusivePtr<DefinitionContents> &);
/** Construct a Definition with the supplied args, values, and reduction domain. */
EXPORT Definition(const std::vector<Expr> &args, const std::vector<Expr> &values,
const ReductionDomain &rdom, bool is_init);
/** Construct an empty Definition. By default, it is a init definition. */
EXPORT Definition();
/** Return a deep copy of this Definition. It recursively deep copies all
* called functions, schedules, and reduction domains. This method
* takes a map of <old FunctionContents, deep-copied version> as input and
* would use the deep-copied FunctionContents from the map if exists instead
* of creating a new deep-copy to avoid creating deep-copies of the same
* FunctionContents multiple times.
*/
EXPORT Definition deep_copy(
std::map<IntrusivePtr<FunctionContents>, IntrusivePtr<FunctionContents>> &copied_map) const;
/** Equality of identity */
bool same_as(const Definition &other) const {
return contents.same_as(other.contents);
}
/** Is this an init definition; otherwise it's an update definition */
EXPORT bool is_init() const;
/** Pass an IRVisitor through to all Exprs referenced in the
* definition. */
EXPORT void accept(IRVisitor *) const;
/** Pass an IRMutator through to all Exprs referenced in the
* definition. */
EXPORT void mutate(IRMutator *);
/** Get the default (no-specialization) arguments (left-hand-side) of the definition */
// @{
EXPORT const std::vector<Expr> &args() const;
EXPORT std::vector<Expr> &args();
// @}
/** Get the default (no-specialization) right-hand-side of the definition */
// @{
EXPORT const std::vector<Expr> &values() const;
EXPORT std::vector<Expr> &values();
// @}
/** Get the predicate on the definition */
// @{
EXPORT const Expr &predicate() const;
EXPORT Expr &predicate();
// @}
/** Split predicate into vector of ANDs. If there is no predicate (i.e. this
* definition is always valid), this returns an empty vector. */
EXPORT std::vector<Expr> split_predicate() const;
/** Get the default (no-specialization) schedule associated with this definition. */
// @{
EXPORT const Schedule &schedule() const;
EXPORT Schedule &schedule();
// @}
/** You may create several specialized versions of a func with
* different schedules. They trigger when the condition is
* true. See \ref Func::specialize */
// @{
EXPORT const std::vector<Specialization> &specializations() const;
EXPORT std::vector<Specialization> &specializations();
EXPORT const Specialization &add_specialization(Expr condition);
// @}
};
struct Specialization {
Expr condition;
Definition definition;
std::string failure_message; // If non-empty, this specialization always assert-fails with this message.
};
}}
#endif