Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions python_bindings/src/halide/halide_/PyStage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void define_stage(py::module &m) {
py::arg("preserved"))
.def("rfactor", static_cast<Func (Stage::*)(const RVar &, const Var &)>(&Stage::rfactor),
py::arg("r"), py::arg("v"))
.def("hoist_invariants", &Stage::hoist_invariants)

.def("eager_inline", (Stage & (Stage::*)(const std::vector<Func> &)) & Stage::eager_inline, py::arg("fs"))
.def("eager_inline", [](Stage &stage, const py::args &args) -> Stage & {
Expand Down
365 changes: 294 additions & 71 deletions src/Func.cpp

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions src/Func.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "Var.h"

#include <map>
#include <type_traits>
#include <utility>

namespace Halide {
Expand Down Expand Up @@ -216,6 +217,44 @@ class Stage {
}
// @}

/** Hoist a loop-invariant factor out of an associative reduction by applying
* the distributive law of a semiring. Like rfactor(), this must be called on
* an update definition; it splits the update into an intermediate that
* accumulates the factor-free reduction over all of the update's RVars and a
* write-back that applies the hoisted factor once. The intermediate Func is
* returned.
*
* A factor is hoistable if it does not depend on any RVar being reduced. It
* may be nested at any depth of an associative/commutative chain. The valid
* hoistings are:
*
* Outer op Inner combine Law
* --------- ------------- ---
* + (sum) * sum_k(s * x_k) = s * sum_k(x_k)
* min + min_k(c + x_k) = c + min_k(x_k)
* max + max_k(c + x_k) = c + max_k(x_k)
* || (bool) && or_k(p && x_k) = p && or_k(x_k)
* && (bool) || and_k(p || x_k) = p || and_k(x_k)
*
* For example, hoist_invariants() rewrites a pipeline like this:
* \code
* f(x) = 0;
* f(x) += s(x) * g(x, r);
* \endcode
* into a pipeline like this:
* \code
* f_intm(x) = 0;
* f_intm(x) += g(x, r);
*
* f(x) = 0;
* f(x) += s(x) * f_intm(x);
* \endcode
*
* This reduces the number of factor applications from |R| to one per pure
* point. It is an error if no distributable invariant factor is found.
*/
Func hoist_invariants();

/** Schedule the iteration over this stage to be fused with another
* stage 's' from outermost loop to a given LoopLevel. 'this' stage will
* be computed AFTER 's' in the innermost fused dimension. There should not
Expand Down
Loading
Loading