root/src/Definition.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


#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

/* [<][>][^][v][top][bottom][index][help] */