MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
reassoc.h
Go to the documentation of this file.
1#pragma once
2
3#include <optional>
4
5#include <mim/phase.h>
6
8
9/// One node of a bracketing: `i … j` splits after `s`.
10/// Spelling the fields out keeps `size_t` out of the type - it is *not* mim::u64 everywhere.
11/// A transposed node @p t is computed as the product of its operands' transposes, `(Rᵀ · Lᵀ)ᵀ`.
12struct Split {
13 u64 i, s, j;
14 bool t = false;
15};
16
17/// A bracketing of a matrix chain, innermost node first.
18using Splits = fe::Vector<Split>;
19
20/// A chain operand; the chain reads its transpose if @p t.
21struct Leaf {
22 const Def* def;
23 bool t;
24};
25
26using Leaves = fe::Vector<Leaf>;
27
28/// Reassociates chains of tensor.product_2d with the classic matrix-chain-order dynamic program,
29/// so that a chain is evaluated with the least number of vector-lane slots.
30///
31/// Extents need not be literal: a cost is kept as a polynomial in the symbolic extents, ordered by
32/// coefficient-wise `≤`.
33/// Since extents are `Nat`s and hence non-negative, that order proves `≤` under *every* instantiation -
34/// but it is only a *partial* order, so a chain can have several bracketings that each win for some
35/// instantiation (a batch dimension favouring a different one when small than when large).
36/// Up to Reassoc::max_dispatch_ matrices those survivors are emitted side by side behind a runtime
37/// comparison of their costs; a longer chain is only reassociated where one bracketing provably wins.
38class Reassoc : public RWPhase {
39public:
40 using RWPhase::RWPhase;
41
42private:
43 static constexpr u64 Default_max_dispatch = 4;
44 static constexpr u64 Default_vec = 8;
45
46 /// One `tensor.product_2d` of a chain: `«m, k» · «k, l»`.
47 struct Link {
48 const App* app;
49 const Def* m;
50 const Def* k;
51 const Def* l;
52 };
53
54 void start() override;
55 const Def* rewrite_imm_App(const App*) final;
56
57 const Def* reassoc(const App*);
58 std::optional<Link> isa_link(const Def* def, const Def* ring) const;
59
60 /// Appends the chain's leaves to @p mats, each leaf's *row* extent to @p dims, and the bracketing as
61 /// written to @p orig; the caller appends the chain's trailing column extent and its own split.
62 void flatten(const Def* def, const Def* ring, const Def* rows, bool t, Leaves& mats, DefVec& dims, Splits& orig);
63
64 /// Rebuilds `mats[i … j]` in the new world, parenthesized according to @p split (indexed `i * n + j`).
65 const Def* build(const Def* head, fe::View<Leaf> mats, Defs dims, fe::View<u64> split, u64 i, u64 j);
66
67 /// Emits every bracketing in @p cands as a thunk and selects the cheapest one by comparing their costs
68 /// at run time.
69 const Def* dispatch(const Def* head, const Def* res_ty, fe::View<Leaf> mats, Defs dims, fe::View<Splits> cands);
70
71 /// The number of lane slots @p splits costs, as a `Nat` expression in the new world.
72 const Def* cost_expr(fe::View<Leaf> mats, Defs dims, const Splits& splits);
73
74 /// Old-world consumer count per `product_2d` and 2-D transpose app, attributed through tuple wrappers.
75 DefMap<u64> consumers_;
76
77 /// Longest chain whose bracketings are enumerated - and, failing a unique winner, dispatched over.
78 /// The number of bracketings is `Catalan(n − 1)`, so this cannot grow much.
79 /// Set with `-X tensor:reassoc-max=<n>`; below `3` nothing is ever dispatched.
80 u64 max_dispatch_ = Default_max_dispatch;
81
82 /// Lanes of the vector loop, which `dot_schedule` runs over each product's trailing extent - or,
83 /// for a transposed operand, `dot_schedule_kvec` over its contraction.
84 /// A literal extent is charged rounded up to a whole number of these, so a bracketing whose
85 /// intermediates are too narrow to fill a vector pays for the lanes it leaves idle.
86 /// Taken from `tensor.vec_width`, i.e. `-X tensor:vec-width=<n>`.
87 u64 vec_ = Default_vec;
88};
89
90} // namespace mim::plug::tensor::phase
Base class for all Defs.
Definition def.h:289
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition phase.h:334
Reassociates chains of tensor.product_2d with the classic matrix-chain-order dynamic program,...
Definition reassoc.h:38
const Def * rewrite_imm_App(const App *) final
Definition reassoc.cpp:376
void start() override
Actual entry.
Definition reassoc.cpp:207
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition phase.h:334
fe::Vector< Split > Splits
A bracketing of a matrix chain, innermost node first.
Definition reassoc.h:18
fe::Vector< Leaf > Leaves
Definition reassoc.h:26
A chain operand; the chain reads its transpose if t.
Definition reassoc.h:21
One node of a bracketing: i … j splits after s.
Definition reassoc.h:12
fe::View< const Def * > Defs
Definition def.h:96
GIDMap< const Def *, To > DefMap
Definition def.h:93
fe::Vector< const Def * > DefVec
Definition def.h:98
uint64_t u64
Definition types.h:27