MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
scalarize.h
Go to the documentation of this file.
1#pragma once
2
3#include <fe/bitset.h>
4
5#include "mim/phase.h"
6
7#include "mim/util/gid.h"
8
9namespace mim {
10
11/// Scalarization (= argument simplification):
12/// ```
13/// f := λ (x_1: [T_1, T_2], .., x_n: T_n).E
14/// ```
15/// becomes
16/// ```
17/// f' := λ (y_1: T_1, y_2: T_2, .. y_n: T_n).E[x_1 \ (y_1, y_2); ..; x_n \ y_n]
18/// ```
19/// It is type-directed: an immutable `Cn` is flattened along with all its Lam%s and App%s, even escaping ones.
20/// A flattened value is coerce()d where it meets an unflattened shape, e.g. an Axm's signature.
21/// An Axm handed a bare function (`autodiff.ad f`) is instantiated with the old shape, as its type may rely on it.
22/// A Pi is pinned where a coercion would be observable:
23/// * a `Cn` an interface Lam's signature reaches through a type coerce() cannot take apart (`mem.Ptr0 K`), or
24/// * a parameter indexed non-constantly or consumed whole by an Axm - only this parameter is kept.
25///
26/// Each run flattens one level; the fixed-point pipeline repeats it.
27/// Flags::scalarize_threshold bounds which Arr%s are expanded.
28class Scalarize : public RWPhase {
29private:
30 /// Optimistic: every immutable `Cn` is flattenable until pinned.
31 class Analysis : public mim::Analysis {
32 public:
34 : mim::Analysis(world, "Scalarize::Analysis") {}
35
36 /// The parameters of @p type to flatten one level; empty means leave it untouched.
37 fe::Bitset plan(const Def* type) const;
38
39 private:
40 const Def* rewrite_mut_Lam(Lam*) final;
41 const Def* rewrite_imm_App(const App*) final;
42 const Def* rewrite_imm_Extract(const Extract*) final;
43 const Def* rewrite_imm_Insert(const Insert*) final;
44
45 /// Keeps @p tuple whole unless the outermost part of @p idx is constant.
46 void keep_indexed(const Def* tuple, const Def* idx);
47 /// Keeps parameter @p dom of @p pi whole.
48 void keep(const Pi* pi, size_t dom);
49 /// Keeps @p def whole if it is a Lam's Var or one of its parameters.
50 void keep_var(const Def* def);
51 bool kept(const Pi* pi, size_t dom) const; ///< Is parameter @p dom of @p pi kept whole?
52 /// Does coerce() see through @p type, i.e. split it or η-wrap it?
53 /// The shape of whatever lies below any other type must be kept.
54 static bool transparent(const Def* type) { return type->isa<Pi>() || splittable(type); }
55 /// pin%s the `Cn`%s below the parts of @p type that coerce() cannot take apart.
56 void pin_opaque(DefSet& structural, const Def* type);
57
58 /// Not in lattice(), as its map() of the Pi would break type arguments like `mem.slot (H, 0)`.
60 };
61
62public:
64 : RWPhase(world, annex, &analysis_)
65 , analysis_(world) {}
66
67private:
68 /// Rebuilds what an interface Lam's signature mentions in its old shape and leaves everything else to Scalarize.
69 class Keep : public Rewriter {
70 public:
71 Keep(Scalarize& sca)
72 : Rewriter(sca.new_world())
73 , sca_(sca) {}
74
75 const Def* rewrite(const Def*) final;
76
77 private:
78 bool has_cn(const Def*);
79
80 Scalarize& sca_;
81 DefMap<bool> has_cn_;
82 };
83
84 const Def* rewrite_imm_Pi(const Pi*) final;
85 const Def* rewrite_imm_App(const App*) final;
86 /// The new Lam for @p old; the old Var maps to its reassembly from the new one.
87 Lam* stub(Lam* old, const fe::Bitset& mask);
88 /// Flattens @p pi%'s domain one level according to @p mask and rewrites its components with @p rw.
89 const Def* flatten(Rewriter& rw, const Pi* pi, const fe::Bitset& mask);
90 const Def* rewrite_mut_Lam(Lam*) final;
91
92 Analysis analysis_;
93};
94
95} // namespace mim
Traverses the current World using Rewriter infrastructure while staying in the same world.
Definition phase.h:130
Base class for all Defs.
Definition def.h:289
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition tuple.h:360
Creates a new Tuple / Pack by inserting Insert::value at position Insert::index into Insert::tuple.
Definition tuple.h:385
A function.
Definition lam.h:91
friend class Analysis
Definition phase.h:106
flags_t annex() const
Definition phase.h:62
A dependent function type.
Definition lam.h:14
World & new_world()
Create new Defs into this.
Definition phase.h:379
static bool splittable(const Def *type)
Does coerce() explode and reassemble values of type?
Definition phase.h:399
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition phase.h:334
World & world()=delete
Hides both and forbids direct access.
Recurseivly rebuilds part of a program into the provided World w.r.t. Rewriter::map.
Definition rewrite.h:21
virtual const Def * rewrite_imm_Extract(const Extract *)
virtual const Def * rewrite_imm_Insert(const Insert *)
Rewriter(World &world)
Definition rewrite.cpp:16
Scalarization (= argument simplification):
Definition scalarize.h:28
const Def * rewrite_imm_Pi(const Pi *) final
const Def * rewrite_imm_App(const App *) final
Scalarize(World &world, flags_t annex)
Definition scalarize.h:63
const Def * rewrite_mut_Lam(Lam *) final
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:43
Definition ast.h:16
ankerl::unordered_dense::map< K, V, GIDHash< K > > GIDMap
Definition gid.h:22
u64 flags_t
Definition types.h:39
GIDSet< const Def * > DefSet
Definition def.h:94
@ Lam
Definition def.h:125