23 const Def *
Tis, *
Ris, *
Sis, *
Tps, *
Rps, *
Sps, *
comb, *
init, *
post, *
maps, *
post_maps;
33 return {
nis_nps,
meta,
shapes,
in_tys,
comb_init,
map_out,
maps_all,
nis,
nps,
To,
34 Tp,
Ro,
Rn,
TSched,
So,
Sr,
sched,
Tis,
Ris,
Sis,
44 std::optional<Ranks>
ranks()
const {
49 if (!nis_l || !nps_l || !ro_l || !rn_l || *rn_l < *ro_l)
return {};
50 return Ranks{*nis_l, *nps_l, *ro_l, *rn_l - *ro_l};
62 auto& w =
mem->world();
64 a = w.app(a,
Defs{s_in, s_out});
67 a = w.app(a,
mem->type()->as<
App>()->
arg());
74 auto& w = caller->
world();
76 args.emplace_back(ret);
77 caller->
app(
true, f, w.tuple(args));
79 caller->
app(
true, f, w.tuple({w.tuple(args), ret}));
85inline std::pair<Lam*, const Def*>
ds_splice(
const Def* arg,
const Def* codom, std::string name) {
86 auto& w = arg->
world();
87 auto fun = w.mut_fun(arg->
type(), codom)->set(std::move(name));
94 return DefVec(iters.size(), [&](
size_t d) { return w.call(core::conv::u, extents[d], iters[d]); });
99 auto& w = shape->world();
100 return *
Shape(w,
to_idxs(w, shape->projs(iters.size()), iters)).fold(shape);
105 auto& w = x->
world();
112 auto& w = lo->
world();
113 auto i64 = w.type_i64();
114 auto rn = iters.size();
117 for (
u64 d = 0; d < rn; ++d) {
126 valid.push_back(v_d);
127 idx_i64 = w.select(v_d, in_d, w.lit_i64(0));
131 if (replicate)
return {coords,
nullptr};
132 auto all_valid = valid.empty() ? w.lit_tt() : valid[0];
133 for (
u64 d = 1; d < valid.size(); ++d)
134 all_valid = w.call(
core::bit2::and_, w.lit_nat(2), w.tuple({all_valid, valid[d]}));
135 return {coords, all_valid};
141 auto exts = fe::Vector<u64>(nis);
142 for (
u64 i = 0; i < nis; ++i)
153 auto& w = o_ax->
world();
155 auto read_i = [&](
u64 i) {
157 return read(i,
clamp(loc, w.lit_i64(exts[i] - 1)));
159 auto result = read_i(0);
160 for (
u64 i = 1; i < exts.size(); ++i) {
163 result = w.select(cond, read_i(i), result);
178 const std::string& name,
180 auto& w =
mem->world();
181 auto [fun, call] =
ds_splice(w.tuple({mem, dst, ins}), result_ty, name);
182 auto [fun_mem, out_buf, fun_ins] = fun->var(2, 0)->projs<3>();
183 const Def* cont = fun->
var(2, 1);
184 const Def* acc = w.tuple({fun_mem, out_buf});
187 auto [loop_mem, loop_buf] = acc->
projs<2>();
189 std::pair<const Def*, const Def*> el = compute(iters, fun_ins, loop_mem);
190 auto [el_mem, elem] = el;
192 cur->app(
true, cont, w.tuple({wr_mem, loop_buf}));
static auto uncurry_args(const Def *def)
const Def * proj(nat_t a, nat_t i) const
Similar to World::extract while assuming an arity of a, but also works on Sigmas and Arrays.
World & world() const noexcept
const Def * var(nat_t a, nat_t i) noexcept
auto projs(Projector auto f) const
Splits this Def via Def::projections into an Array (if A == std::dynamic_extent) or std::array (other...
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
nat_t num_projs() const
Yields Def::arity(), if it is a Lit, or 1 otherwise.
Lam * app(Filter filter, const Def *callee, const Def *arg)
Set body to an App of callee and arg.
static std::optional< T > isa(const Def *def)
A dependent function type.
constexpr Shape() noexcept=default
The World represents the whole program and manages creation of MimIR nodes (Defs).
DefVec counting_nest(Lam *&cur, const Def *&exit, const Def *&acc, Defs dims, std::string_view name)
Nests one counting loop per bound of dims inside cur, threading cur, exit and acc down to the innermo...
const Def * op_affine_map(const Def *f, const Def *m, const Def *n, const Def *s_in, const Def *s_out, const Def *idxs, const Def *mem)
affine.map @(m, n) @(s_in, s_out) f idxs as mem with the address space as of mem ↦ [mem',...
std::optional< fe::Vector< u64 > > concat_extents(const Def *Sis, u64 nis, u64 r, u64 ax)
The literal extents of the nis input shapes Sis along the concat axis ax; std::nullopt if one is not ...
DefVec to_idxs(World &w, Defs extents, Defs iters)
Converts the raw i64 loop counters iters into indices Idx extents[d].
const Def * build_pointwise(const Def *result_ty, const Def *mem, const Def *dst, const Def *ins, const Def *s_out, u64 rn, const std::string &name, auto compute)
A [mem, dst, ins] → [mem, Buf] fun spliced via cps.cps2ds_dep that loops over s_out carrying [mem,...
const Def * clamp(const Def *x, const Def *hi)
Clamps the i64 x into [0, hi].
std::pair< DefVec, const Def * > pad_coords(Defs iters, const Def *lo, const Def *s_in, bool replicate)
The read coordinates o#d − lo#d of a pad into Idx s_in#d - clamped to the nearest edge if replicate,...
const Def * folded_idx(const Def *shape, Defs iters)
The raw i64 loop counters iters as a buffer index into shape, with its literal size-1 axes folded awa...
const Def * concat_select(const Def *o_ax, const fe::Vector< u64 > &exts, auto read)
The concat cell at the i64 axis coordinate o_ax: read(i, loc) of the input i owning it - the highest ...
std::pair< Lam *, const Def * > ds_splice(const Def *arg, const Def *codom, std::string name)
A fresh fun: Fn arg->type() → codom named name, spliced into direct style as cps.cps2ds_dep fun arg.
void app_cps(Lam *caller, const Def *f, DefVec args, const Def *ret)
Calls the combiner/epilogue f from caller with args and the continuation ret.
const Def * op_write(const Def *r, const Def *s, const Def *T, const Def *mem, const Def *buf, const Def *idx, const Def *val)
buffer.write (r, s, T) (mem, buf, idx, val) ↦ [mem.M 0, buffer.Buf (r, s, T)].
const Def * op_cps2ds_dep(const Def *k)
fe::View< const Def * > Defs
fe::Vector< const Def * > DefVec
The curried meta arguments of a tensor.map_reduce_post or btensor.map_reduce_post callee (same layout...
static MapRedPost of(const App *callee)
std::optional< Ranks > ranks() const
The literal input counts and loop ranks; std::nullopt unless all are literal and Rn >= Ro.