MimIR
0.4-dev
MimIR is my Intermediate Representation
Toggle main menu visibility
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
namespace
mim
{
8
9
/// Perform Scalarization (= Argument simplification).
10
/// This means that, e.g.,
11
/// ```
12
/// f := λ (x_1: [T_1, T_2], .., x_n: T_n).E
13
/// ```
14
/// will be transformed to
15
/// ```
16
/// f' := λ (y_1: T_1, y_2: T_2, .. y_n: T_n).E[x_1 \ (y_1, y_2); ..; x_n \ y_n]
17
/// ```
18
///
19
/// The transformation is **type-directed**:
20
/// the decision to flatten is made per continuation *type* (immutable `Cn`) - not per Lam.
21
/// Every producer and consumer of such a type is reshaped in the same sweep:
22
/// the Pi itself, all Lam%s of that type, and all App%s through it - no matter whether the callee is a mutable Lam,
23
/// a Var (higher-order parameter), a branch tuple, or a value loaded back from memory.
24
/// Hence, a Lam may escape (be stored, passed as argument) and still get its signature flattened.
25
///
26
/// A Pi is *pinned* (left untouched) if
27
/// * it is reachable from an annex (normalizers and backends rely on its exact shape),
28
/// * an Axm application's signature dictates it - what the Axm consumes and produces,
29
/// plus a *bare* function argument's type (`autodiff.ad f`) - except for subtrees that are
30
/// merely substituted in via (type) arguments (`T` in `mem.store T`), which stay flattenable,
31
/// * it occurs inside an *interface* Lam's signature (external, annex, or unset declaration) -
32
/// only such a Lam's own top-level Pi stays flattenable (it may be shared with internal values;
33
/// rewrite_mut_Lam() preserves the interface's top level by hand),
34
/// * it types a value inside a dependently-typed aggregate (a typed closure),
35
/// * an App connects a dom and an arg whose types are alpha-equivalent yet *distinct* defs, or
36
/// * one of its parameters is Extract%ed / Insert%ed via a **non-constant** index
37
/// (splitting would only force the body to reassemble the tuple);
38
/// this is tracked per parameter via a keep-bitmask.
39
///
40
/// The phase flattens **one level** of a Pi's (thresholded) domain per run.
41
/// Because it is scheduled inside a fixed-point pipeline (`compile.phases tt (...)`),
42
/// re-running it converges to a full flatten; each run that peels calls invalidate().
43
///
44
/// Flattening respects Flags::scalarize_threshold via the thresholded projection helpers
45
/// (Def::num_tprojs, Pi::tdom, App::targ): a parameter is only expanded if its arity is
46
/// below the threshold.
47
/// It will not flatten mutable @p Sigma%s or @p Arr%ays (their vars have no static arity).
48
class
Scalarize
:
public
RWPhase
{
49
private
:
50
/// Optimistic fixed-point analysis: every immutable `Cn` is assumed flattenable
51
/// until proven otherwise (see the pinning rules above).
52
class
Analysis :
public
mim::Analysis
{
53
public
:
54
Analysis
(
World
&
world
)
55
:
mim::Analysis
(
world
,
"Scalarize::Analysis"
) {}
56
57
/// Per-parameter expand mask for @p type; a set bit marks a parameter to be flattened one level.
58
/// An **empty** mask means "leave untouched".
59
/// Cheap; recomputed on demand from the (post-fixed-point) lattice.
60
fe::Bitset plan(
const
Def
* type)
const
;
61
62
private
:
63
const
Def
*
rewrite
(
const
Def
* old)
final
;
64
65
void
inspect(
const
Def
* def);
66
/// Marks parameter @p dom of @p pi as *keep whole* by OR-ing bit @p dom into a per-Pi bitmask stored
67
/// in lattice() under @p pi.
68
/// We store the fact via lattice_force() - **not** via lattice(concr, abstr)/pin():
69
/// growing the mask swaps one Nat literal for another - non-monotone in terms of Def%s.
70
/// As with any lattice write, the bitmask also lands in the rewriter map(),
71
/// short-circuiting later rewrite(pi) calls to the Nat.
72
/// That is harmless for this same-World Analysis:
73
/// drain() discards rewrite results, and inspect() always receives the old def.
74
/// A fresh bit invalidate()s.
75
void
keep(
const
Pi
* pi,
size_t
dom);
76
void
pin_tree(
const
Def
* def);
///< pin%s every flattenable Pi nested in @p def%'s type tree.
77
/// As above, but skips defs already in @p visited - seed it to exempt subtrees from pinning.
78
void
pin_tree(
const
Def
* def,
DefSet
& visited);
79
bool
kept(
const
Pi
* pi,
size_t
dom)
const
;
///< Is parameter @p dom of @p pi kept whole?
80
};
81
82
public
:
83
Scalarize
(
World
&
world
,
flags_t
annex
)
84
:
RWPhase
(
world
,
annex
, &analysis_)
85
, analysis_(
world
) {}
86
87
private
:
88
const
Def
*
rewrite_imm_Pi
(
const
Pi
*)
final
;
89
const
Def
*
rewrite_mut_Lam
(
Lam
*)
final
;
90
const
Def
*
rewrite_imm_App
(
const
App
*)
final
;
91
92
/// Flattens @p app%'s arguments one level according to @p mask.
93
DefVec
flatten_args(
const
App
* app,
const
fe::Bitset& mask);
94
95
Analysis
analysis_;
96
};
97
98
}
// namespace mim
mim::Analysis
Traverses the current World using Rewriter infrastructure while staying in the same world.
Definition
phase.h:151
mim::App
Definition
lam.h:224
mim::Def
Base class for all Defs.
Definition
def.h:273
mim::Lam
A function.
Definition
lam.h:113
mim::Phase::Analysis
friend class Analysis
Definition
phase.h:125
mim::Phase::annex
flags_t annex() const
Definition
phase.h:81
mim::Pi
A dependent function type.
Definition
lam.h:14
mim::RWPhase::RWPhase
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition
phase.h:431
mim::RWPhase::world
World & world()=delete
Hides both and forbids direct access.
mim::Rewriter::rewrite
virtual const Def * rewrite(const Def *)
Definition
rewrite.cpp:55
mim::Scalarize::rewrite_imm_Pi
const Def * rewrite_imm_Pi(const Pi *) final
Definition
scalarize.cpp:202
mim::Scalarize::rewrite_imm_App
const Def * rewrite_imm_App(const App *) final
Definition
scalarize.cpp:275
mim::Scalarize::Scalarize
Scalarize(World &world, flags_t annex)
Definition
scalarize.h:83
mim::Scalarize::rewrite_mut_Lam
const Def * rewrite_mut_Lam(Lam *) final
Definition
scalarize.cpp:225
mim::World
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition
world.h:40
mim
Definition
ast.h:16
mim::flags_t
u64 flags_t
Definition
types.h:39
mim::DefVec
fe::Vector< const Def * > DefVec
Definition
def.h:93
mim::DefSet
GIDSet< const Def * > DefSet
Definition
def.h:89
phase.h
include
mim
phase
scalarize.h
Generated by
1.18.0