29 static const Def*
cat(
bool term,
const Def* a,
const Def* b);
34 static constexpr size_t Num_Ops = std::dynamic_extent;
43 Sigma(
const Def*
type,
size_t size)
51 Sigma*
set(
size_t i,
const Def* def) {
return Def::set(i, def)->as<Sigma>(); }
118 static constexpr size_t Gone = size_t(-1);
125 , new2old_(num, [](size_t i) {
return i; }) {}
128 Sieve(
size_t num, std::predicate<size_t>
auto pred)
130 new2old_.reserve(num);
131 for (
size_t i = 0; i != num; ++i)
132 if (pred(i)) new2old_.emplace_back(i);
137 :
Sieve(ops.size(), [ops, pred](size_t i) {
return pred(ops[i]); }) {}
145 void cat(
size_t num, std::predicate<size_t>
auto pred) {
146 new2old_.reserve(new2old_.size() + num);
147 for (
size_t i = 0; i != num; ++i)
149 new2old_.emplace_back(num_ + i);
157 size_t cat(
size_t i)
const {
return (*
this)[
num_old() + i]; }
162 size_t num_old()
const {
return num_ - num_cat_; }
163 size_t num_new()
const {
return new2old_.size(); }
168 assert(num_cat_ == 0 &&
"rewrite_stub cannot rewrite a concat'ed component from an old op");
173 auto j = std::ranges::lower_bound(new2old_, i);
174 return j != new2old_.end() && *j == i ? size_t(j - new2old_.begin()) :
Gone;
178 assert(ops.size() == num_);
179 return DefVec(
num_new(), [
this, ops](
size_t i) {
return ops[new2old_[i]]; });
186 size_t num_cat_new_ = 0;
187 fe::Vector<size_t> new2old_;
196 constexpr Shape() noexcept = default;
205 constexpr explicit operator bool() const noexcept {
return def_ !=
nullptr; }
212 std::optional<nat_t>
rank()
const;
217 assert(r &&
"a dynamic rank has no statically indexable axes");
218 return def_->proj(*r, i);
223 static std::optional<nat_t>
extent(
const Def* axis);
243 if (
auto r =
rank()) {
246 for (
nat_t i = 0; i != *r; ++i)
247 if (
auto a = def_->proj(*r, i); keep(i, a)) kept.emplace_back(a);
249 return kept.size() == *r ? *this :
Shape(def_->world(), kept);
263 const Def* def_ =
nullptr;
360class Extract :
public Def,
public Setters<Extract> {
385class Insert :
public Def,
public Setters<Insert> {
412 explicit operator bool() const noexcept {
return extract_; }
445 explicit operator bool() const noexcept {
return app_; }
452 const App* app_ =
nullptr;
470 explicit operator bool() const noexcept {
return app_; }
477 const App* app_ =
nullptr;
static constexpr auto Node
static constexpr size_t Num_Ops
Arr * set_body(const Def *body)
Arr * set(const Def *shape, const Def *body)
Arr * set_shape(const Def *shape)
const Def * callee() const
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.
Def * set(size_t i, const Def *)
Successively set from left to right.
constexpr auto ops() const noexcept
const Def * op(size_t i) const noexcept
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
const Def * arity() const
Number of elements available to Extract / Insert (may be dynamic).
Def * unset()
Unsets all Def::ops; works even, if not set at all or only partially set.
constexpr auto reduce(const Def *arg) const
const Def * callee() const
static constexpr auto Node
const Def * tuple() const
const Def * index() const
static constexpr size_t Num_Ops
const Def * value() const
static T as(const Def *def)
Pack * set_body(const Def *body)
Pack * set_shape(const Def *shape)
static constexpr size_t Num_Ops
Pack * set(const Def *shape, const Def *body)
static constexpr auto Node
Base class for Sigma and Tuple.
static constexpr bool isa_node(mim::Node n) noexcept
Prod groups Sigma and Tuple; see fe::NodeSetable.
static DefVec cat_projs(nat_t n, nat_t m, const Def *a, const Def *b)
The spliced components themselves - for when you want to build something other than a Prod from them.
static const Def * cat(bool term, nat_t n, nat_t m, const Def *a, const Def *b)
static constexpr size_t Num_Ops
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Base class for Arr and Pack.
static constexpr bool isa_node(mim::Node n) noexcept
Seq groups Arr and Pack; see fe::NodeSetable.
Seq * set(const Def *shape, const Def *body)
Common setter for Packs and Arrays.
const Def * elem() const
The element one axis down: Seq::body for a one-dimensional Seq, the Seq of the remaining axes otherwi...
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
const Def * reduce(const Def *arg) const
CRTP-based mixin to declare setters for Def::loc & Def::name using a covariant return type.
const Tuple * set(Args &&... args) const
The extents of a Seq's axes: a plain Nat for a single axis, an aggregate of them for several.
Shape zonk() const
Wraps Def::zonk();.
std::optional< nat_t > rank() const
Number of axes; std::nullopt if not statically known.
bool is_fused() const
Does this span several axes? Also true for a dynamic rank.
static std::optional< nat_t > extent(const Def *axis)
The extent of axis: the axis itself for a shape, its Idx size for an index.
const Def * front() const
The outermost axis - the Def::arity of the Seq this shape describes; null for a null Shape.
Shape operator+(Shape) const
Concatenation - what fuses «a; «b; T»» into «a, b; T».
bool is_dim() const
Is this a single axis - a Nat/Idx rather than an aggregate of them?
constexpr const Def * operator->() const noexcept
Shape slice(nat_t begin, nat_t end) const
The axes [begin, end).
Shape fold() const
Drops every literal size-1 axis, mirroring «1; T» ≡ T; all of them folded away leaves rank 0.
const Def * operator[](nat_t i) const
The i th axis.
static bool isa_extents(const Def *)
Is type Nat - or an aggregate of Nats, i.e. a shape?
Shape drop(nat_t n) const
All but the leading n axes.
constexpr const Def * operator*() const noexcept
Shape filter(auto keep) const
This Shape with only the axes keep accepts; *this, if it accepts all of them or the rank is dynamic.
Shape take(nat_t n) const
The leading n axes.
constexpr Shape() noexcept=default
static bool isa_indices(const Def *)
Is type Idx - or an aggregate of Idxs, i.e. a fused index?
size_t num_cat() const
Number of concat'ed candidates.
size_t cat(size_t i) const
As Sieve::operator[] but for concat'ed i.
void cat(size_t num, std::predicate< size_t > auto pred)
DefVec gather(Defs ops) const
The surviving components of ops - one per candidate, concat'ed ones included.
Sieve(Defs ops, std::predicate< const Def * > auto pred)
Keeps those ops that satisfy pred.
fe::View< size_t > new2old() const
The old index of the i th survivor; this is what Rewriter::rewrite_stub expects.
size_t num_new() const
Number of survivors.
size_t num_old() const
Number of old components.
size_t operator[](size_t i) const
The new index of the candidate i - or Sieve::Gone, if it didn't survive.
static constexpr size_t Gone
bool all() const
Is the new aggregate the old one - nothing dropped and nothing concat'ed?
Sieve(size_t num, std::predicate< size_t > auto pred)
Keeps those of num candidates that satisfy pred.
static const Def * cat(nat_t n, nat_t m, const Def *a, const Def *b)
static const Def * infer(World &, Defs)
static constexpr auto Node
Sigma * set(size_t i, const Def *def)
static const Def * cat(const Def *a, const Def *b)
size_t num_targets() const
const Extract * extract() const
const Def * index() const
const Def * target(size_t i) const
const Def * tuple() const
static const Def * cat(nat_t n, nat_t m, const Def *a, const Def *b)
static const Def * cat(const Def *a, const Def *b)
static const Def * infer(World &, Defs)
static constexpr auto Node
The World represents the whole program and manages creation of MimIR nodes (Defs).
bool is_unit(const Def *)
fe::View< const Def * > Defs
std::string tuple2str(const Def *)
const Def * tuple_of_types(const Def *t)
fe::Vector< const Def * > DefVec