MimIR
0.5-dev
MimIR is my Intermediate Representation
Toggle main menu visibility
Loading...
Searching...
No Matches
seo.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <fe/worklist.h>
4
5
#include <
mim/def.h
>
6
#include <
mim/phase.h
>
7
#include <
mim/tuple.h
>
8
9
#include <
mim/util/gid.h
>
10
11
namespace
mim::plug::mem::phase
{
12
13
/// Symbolic Expression Optimization.
14
/// Based on [SSA Translation Is an Abstract Interpretation](https://dl.acm.org/doi/10.1145/3571258).
15
/// In addition:
16
/// * propagates whole expressions - not just constants
17
/// * optimistically combines φs/Vars that are already present with those being constructed through SSA translation
18
/// * since abstract domain is a MimIR expression, stack slots themselves can be propagated etc.
19
/// * contifies for free: a continuation parameter that all call sites agree on is propagated away
20
///
21
/// Additional papers worth reading:
22
/// * [Constant propagation with conditional branches](https://dl.acm.org/doi/pdf/10.1145/103135.103136)
23
/// * [Detecting equality of variables in programs](https://dl.acm.org/doi/10.1145/73560.73561)
24
/// * [Combining analyses, combining optimizations](https://dl.acm.org/doi/pdf/10.1145/201059.201061)
25
/// * [Simple and efficient construction of static single assignment
26
/// form](https://dl.acm.org/doi/10.1007/978-3-642-37051-9_6)
27
/// * [Contification using dominators](https://dl.acm.org/doi/10.1145/507635.507639)
28
///
29
/// Due to MimIR's sea of node structure a number of other optimizations kick in such as arithmetic simplifications and
30
/// code motion.
31
///
32
/// Lattice per Lam::var:
33
/// ```
34
/// ⊤ ← Keep as is
35
/// |
36
/// Bundle ← Vars that (horizontally) behave the same build a single congruence class
37
/// |
38
/// Expr ← Whole expression is propagated (vertically) through var
39
/// |
40
/// ⊥
41
/// ```
42
/// A var that has reached ⊤ for propagation but still awaits GVN bundling is marked with a dedicated Proxy sentinel.
43
class
SEO
:
public
RWPhase
{
44
private
:
45
using
Super =
mim::RWPhase
;
46
47
class
Analysis :
public
mim::Analysis
{
48
public
:
49
using
Super =
mim::Analysis
;
50
51
Analysis
(
World
&
world
)
52
:
mim::Analysis
(
world
,
"SEO::Analyzer"
) {}
53
54
void
reset
()
final
;
55
56
const
LamSet
& unknowns()
const
{
return
unknowns_; }
57
58
// SSA
59
const
auto
& slots()
const
{
return
slots_; }
60
const
Def
* lam2sloxy2val(
Lam
* lam,
const
Def
* sloxy);
61
/// Can *every* recorded call site of @p lam supply a value for @p sloxy?
62
/// Only then may build_args() find an argument for a phi threaded through @p lam.
63
bool
can_supply(
Lam
* lam,
const
Def
* sloxy);
64
65
private
:
66
// SCCP
67
const
Proxy
* mk_sccp_top(
const
Def
* var);
68
const
Def
* sccp_join(
Lam
*,
const
Def
*,
const
Def
*);
69
70
/// Applies @p known to @p abstr_targs (one per tvar): propagates phis, runs SCCP + GVN, and sets the vars.
71
const
Def
* apply_known(
Lam
* known,
Defs
abstr_targs);
72
/// An App that merely records "@p callee applied to these abstract args"; never emitted code.
73
const
Def
* abstract_app(
const
Def
* callee,
const
Def
* arg);
74
75
// GVN
76
const
Proxy
* mk_bundle(
Lam
* lam,
const
Def
* var,
Defs
bundle_vars);
77
void
gvn_bundle(
Lam
*,
Defs
,
Defs
, fe::Span<const Def*>);
78
void
gvn_split(
Lam
*,
Defs
, fe::Span<const Def*>, fe::Span<const Def*>);
79
80
// SSA
81
/// Grows lam2live_ by closing @p lam's free Var%s and @p abstr_args over the lattice and slot2stored_.
82
void
live(
Lam
* lam,
Defs
abstr_args);
83
using
VarWorklist = fe::DFSWorklist<GIDSet<const Var*>>;
84
/// The slot Var%s reachable from @p todo through the lattice and slot2stored_.
85
Vars
reachable_slots(VarWorklist&
todo
);
86
/// Like free_vars() but skips mem-typed parts, which cannot carry a slot's ptr.
87
Vars
non_mem_free_vars(
const
Def
* def);
88
/// A direct-style call may access every slot reachable from the non-mem parts of its abstract callee and arg.
89
void
pin_reachable_slots(
const
Def
* abstr_callee,
const
Def
* abstr_arg);
90
void
pin_slot(
const
App
*
slot
);
91
/// Writes `concr ↦ abstr` resolved against @p sloxy, which pin_slot erases again.
92
void
resolve(
const
Def
* sloxy,
const
Def
* concr,
const
Def
* abstr);
93
void
propagate_phis(
Lam
*,
DefVec
& vars,
DefVec
& abstr_args);
94
const
Def
* sloxy2val(
const
Def
* sloxy) {
return
lam2sloxy2val(
curr_mut<Lam>
(), sloxy); }
95
const
Def
* sloxy2val(
const
Def
* sloxy,
const
Def
* val) {
return
lam2sloxy2val_[
curr_mut<Lam>
()][sloxy] = val; }
96
const
Def
*
rewrite_imm_App
(
const
App
*)
final
;
97
void
leave
()
final
;
98
99
// post-processing analysis to find sloxies that must be set to top
100
void
finalize
()
final
;
101
void
analyze
(
const
Def
*);
102
103
// local (reset between iterations)
104
LamMap<Def2Def>
lam2sloxy2val_;
105
DefSet
visited_;
106
DefSet
first_;
107
DefMap<Vars>
non_mem_fvs_;
108
109
// global (kept between iterations)
110
DefSet
slots_;
// actually slot ptrs
111
VarMap<const App*>
var2slot_;
// slot continuation Var ↦ its slot
112
VarMap<Vars>
slot2stored_;
// free Var%s of the values stored behind a slot
113
VarMap<DefSet>
slot2resolved_;
// promoted leas and loaded values whose lattice entry depends on the slot
114
LamMap<Vars>
lam2live_;
// slot Var%s a Lam may access; only grows
115
LamSet
unknowns_;
// Lam%s reached as a *value*; their signature must stay untouched
116
LamMap<MutSet>
lam2callers_;
// all muts that apply a Lam; tainted when the Lam's abstract vars change
117
};
118
119
public
:
120
SEO
(
World
&
world
,
flags_t
annex
)
121
:
RWPhase
(
world
,
annex
, &analysis_)
122
, analysis_(
world
) {}
123
124
private
:
125
const
Def
*
rewrite_imm_App
(
const
App
*)
final
;
126
const
Def
*
rewrite_imm_Var
(
const
Var
*)
final
;
127
const
Def
*
rewrite_mut_Lam
(
Lam
*)
final
;
128
129
/// A live phi for a Lam: the @p sloxy it stands for, the @p phi proxy, and its abstract @p val.
130
struct
Phi {
131
const
Def
* sloxy;
132
const
Def
* phi;
133
const
Def
* val;
134
};
135
136
/// The new signature of an old Lam: the old Lam's tvars sieved, with Sig::phis appended as further candidates.
137
/// So Sieve::num_new is the new Lam's arity, Sieve::operator[] the new index of an old tvar,
138
/// and Sieve::cat the new index of a phi.
139
struct
Sig {
140
fe::Vector<Phi> phis;
///< Its live phis.
141
Sieve
sieve{0};
///< @see Sig
142
bool
todo
=
false
;
///< Does the old Lam need a new signature at all?
143
};
144
145
bool
analyze
() final;
146
147
/// Does @p old_ptr point (via literal mem.lea%s) into a promoted slot? Then yields its sloxy.
148
const
Def
* isa_promoted(const
Def
* old_ptr) const;
149
/// The (memoized) new signature of @p old_lam.
150
const Sig& sig_of(
Lam
* old_lam);
151
/// The new spelling of @p old_lam's var: kept projections become new vars, dropped ones their
152
/// propagated value (⊥ for a promoted slot). The single source of truth for both build_lam() and
153
/// rewrite_imm_Var(), and hence well-defined independent of build order.
154
const
Def
* var_of(
Lam
* old_lam);
155
/// Builds (and caches) the new Lam for @p old_lam with propagated vars removed and kept phis appended.
156
Lam
* build_lam(
Lam
* old_lam);
157
/// Builds the argument list for a jump to @p old_lam (with the given @p old_targs, one per tvar)
158
/// matching the signature built by build_lam().
159
DefVec
build_args(
Lam
* old_lam,
Defs
old_targs);
160
161
Analysis
analysis_;
162
Lam2Lam
lam_old2new_;
163
Lam2Lam
lam_new2old_;
164
GIDNodeMap
<
Lam
*, Sig> lam2sig_;
// a Sig& outlives nested rewrites
165
DefVec
sloxies_;
// the eliminated sloxies; every Lam's phi candidates
166
};
167
168
}
// namespace mim::plug::mem::phase
mim::Analysis
Traverses the current World using Rewriter infrastructure while staying in the same world.
Definition
phase.h:130
mim::Analysis::leave
virtual void leave()
Called after curr_mut() has been completely dealt with.
Definition
phase.h:292
mim::App
Definition
lam.h:215
mim::Def
Base class for all Defs.
Definition
def.h:289
mim::Lam
A function.
Definition
lam.h:91
mim::Phase::Analysis
friend class Analysis
Definition
phase.h:106
mim::Phase::annex
flags_t annex() const
Definition
phase.h:62
mim::Phase::todo
bool todo() const
Definition
phase.h:71
mim::Proxy
Used as intermediate value during optimizatinos such as Analysis.
Definition
def.h:1065
mim::RWPhase
Rebuilds old_world() into new_world() and then swaps them.
Definition
phase.h:330
mim::RWPhase::finalize
virtual void finalize()
Run after all roots have been walked but still before the two worlds are swapped.
Definition
phase.h:406
mim::RWPhase::RWPhase
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition
phase.h:334
mim::RWPhase::world
World & world()=delete
Hides both and forbids direct access.
mim::Rewriter::curr_mut
D * curr_mut() const
Definition
rewrite.h:98
mim::Rewriter::reset
void reset()
Definition
rewrite.cpp:23
mim::Sieve
Filters the components of an aggregate and keeps track of where the survivors end up.
Definition
tuple.h:116
mim::Var
A variable introduced by a binder (mutable).
Definition
def.h:857
mim::World
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition
world.h:43
mim::plug::mem::phase::SEO::analyze
bool analyze() final
Runs the optional pre-analysis on old_world(), typically to a fixed point, before rewriting begins.
Definition
seo.cpp:551
mim::plug::mem::phase::SEO::rewrite_imm_Var
const Def * rewrite_imm_Var(const Var *) final
Definition
seo.cpp:653
mim::plug::mem::phase::SEO::rewrite_imm_App
const Def * rewrite_imm_App(const App *) final
Definition
seo.cpp:589
mim::plug::mem::phase::SEO::rewrite_mut_Lam
const Def * rewrite_mut_Lam(Lam *) final
Definition
seo.cpp:645
mim::plug::mem::phase::SEO::SEO
SEO(World &world, flags_t annex)
Definition
seo.h:120
def.h
gid.h
mim::plug::mem::phase
Definition
add_mem.h:5
mim::plug::mem::slot
slot
Definition
autogen.h:70
mim::LamSet
GIDSet< Lam * > LamSet
Definition
lam.h:211
mim::flags_t
u64 flags_t
Definition
types.h:39
mim::Defs
fe::View< const Def * > Defs
Definition
def.h:96
mim::VarMap
GIDMap< const Var *, To > VarMap
Definition
def.h:114
mim::DefMap
GIDMap< const Def *, To > DefMap
Definition
def.h:93
mim::Lam2Lam
LamMap< Lam * > Lam2Lam
Definition
lam.h:212
mim::LamMap
GIDMap< Lam *, To > LamMap
Definition
lam.h:210
mim::DefVec
fe::Vector< const Def * > DefVec
Definition
def.h:98
mim::DefSet
GIDSet< const Def * > DefSet
Definition
def.h:94
mim::Vars
fe::Patricia< const Var, DefKey >::Set Vars
Definition
def.h:115
mim::GIDNodeMap
ankerl::unordered_dense::segmented_map< K, V, GIDHash< K > > GIDNodeMap
Definition
gid.h:25
phase.h
tuple.h
include
mim
plug
mem
phase
seo.h
Generated by
1.18.0