MimIR
0.5-dev
MimIR is my Intermediate Representation
Toggle main menu visibility
Loading...
Searching...
No Matches
escape_analysis.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <optional>
4
5
#include <
mim/phase.h
>
6
7
#include "
mim/plug/mem/mem.h
"
8
9
namespace
mim::plug::mem
{
10
11
/// Determines which allocations stay within the scope that allocates them.
12
///
13
/// The *home* of an allocation is the Lam on whose memory chain it sits.
14
/// An allocation *escapes* if it flows into the data of a tail call - returned, or handed to a callee or continuation -
15
/// or if an escaping Lam mentions it.
16
/// Any op but `mem.load`, the address of a `mem.store`, and a `mem.free` of the allocation itself may retain the
17
/// pointers it is handed, so they escape there. A Lam escapes if its use is *unknown* - it is used as a value - or if
18
/// an escaping Lam jumps to it. An axiom in control position is assumed to only pass control on to the continuations it
19
/// receives.
20
///
21
/// A buffer-typed parameter of a Lam takes on the value its known call sites pass, as in SCCP.
22
/// An external Lam has unknown call sites, so whatever is passed to it escapes.
23
/// A value only flows into a Lam that its scope strictly encloses; otherwise it would outlive its scope and escapes.
24
///
25
/// Lattice: an escaping allocation is ⊤ - keep as is; *absent* means it stays local.
26
/// A parameter is ⊤ if its call sites disagree; everything they pass escapes.
27
class
EscapeAnalysis
:
public
mim::Analysis
{
28
public
:
29
struct
Chain
{
30
const
App
*
tail
;
31
fe::Vector<const App*>
ops
;
///< The ops threading the memory from the Lam's Var to its tail, in program order.
32
DefMap<size_t>
last
;
///< Per allocation the ops mention: the index of the last op that does so.
33
DefVec
targets
;
///< The continuations the tail transfers control to.
34
};
35
36
EscapeAnalysis
(
World
&
world
)
37
:
mim
::
Analysis
(
world
,
"mem::EscapeAnalysis"
) {}
38
39
static
bool
allocates
(
const
App
* app) {
return
Axm::isa<mem::alloc>
(app) ||
Axm::isa<mem::malloc>
(app); }
40
41
/// @name Results
42
///@{
43
/// The Lam%s with an intact memory chain.
44
const
LamMap<Chain>
&
chains
()
const
{
return
chains_; }
45
/// May @p lam run at any time, as it is used as a value or jumped to by an escaping Lam?
46
bool
escaping
(
Lam
* lam)
const
{
return
escaping_.contains(lam); }
47
/// Is the local @p alloc only mentioned on its home's own memory chain?
48
bool
confined
(
const
Def
*
alloc
)
const
{
return
!shared_.contains(
alloc
); }
49
/// Does a `mem.free` release @p alloc?
50
bool
freed
(
const
Def
*
alloc
)
const
{
return
freed_.contains(
alloc
); }
51
/// The allocation @p def releases if it is a `mem.free` of one; `nullptr` otherwise.
52
static
const
App
*
freed_alloc
(
const
Def
* def) {
53
if
(
auto
free
=
Axm::isa<mem::free>
(def))
54
if
(
auto
ex =
free
->arg(2, 1)->isa<
Extract
>())
55
if
(
auto
app = ex->tuple()->isa<
App
>(); app &&
allocates
(app))
return
app;
56
return
nullptr
;
57
}
58
///@}
59
60
private
:
61
/// Records what each value may carry: the allocations it aliases and the nested Lam%s in it.
62
const
Def
*
rewrite_imm
(
const
Def
*)
override
;
63
const
Def
*
rewrite_imm_App
(
const
App
*)
override
;
64
void
leave
()
override
;
65
66
bool
may_hold(
const
Def
* type)
const
;
67
std::optional<fe::Vector<const App*>> walk(
Lam
* lam,
const
App
* tail);
68
/// Yields where @p mem starts in @p lam - its memory Var or the memory it captures - or `nullptr` if lost.
69
/// Collects the @p ops on the way in reverse program order.
70
const
Def
* walk(
Lam
* lam,
const
Def
*
mem
, fe::Vector<const App*>& ops);
71
/// The memory @p tail hands on - directly or captured by the continuation of a direct-style call.
72
const
Def
* exit_mem(
const
App
* tail,
LamSet
& done);
73
/// Adds what @p def may carry to @p carried, possibly twice; a nested Lam carries itself.
74
void
join(
DefVec
& carried,
const
Def
* def)
const
;
75
76
void
escape(
Lam
* lam) {
77
if
(escaping_.emplace(lam).second)
taint
(lam),
touch
();
78
}
79
/// Everything @p def may carry escapes.
80
void
escape(
const
Def
* def);
81
82
/// The Lam%s a tail jumps to directly - itself or through a jump table - or nothing.
83
static
fe::Vector<Lam*> jumps(
const
Def
* callee);
84
void
jump(
Lam
* k,
const
App
* tail,
DefVec
& targets);
85
/// Joins @p val into @p k%'s parameter @p var.
86
void
propagate(
Lam
* k,
const
Def
* var,
const
Def
* val);
87
/// A continuation handed to a tail transfers control; anything else escapes.
88
void
pass(
const
Def
* def,
DefVec
& targets) {
Pi::isa_cn
(def->
type
()) ? control(def, targets) : escape(def); }
89
/// Collects the continuations a tail transfers control to; the data along the way escapes.
90
void
control(
const
Def
* def,
DefVec
& targets);
91
92
LamMap<Chain>
chains_;
93
DefMap<DefVec>
aliases_;
///< What a value may carry; *absent* means nothing.
94
DefSet
shared_;
95
DefSet
freed_;
96
LamSet
escaping_;
97
};
98
99
}
// namespace mim::plug::mem
mim::Analysis
Traverses the current World using Rewriter infrastructure while staying in the same world.
Definition
phase.h:130
mim::Analysis::Analysis
Analysis(World &world, std::string name)
Definition
phase.h:134
mim::Analysis::taint
void taint(Def *mut)
Additionally schedules mut for the next sparse round.
Definition
phase.h:247
mim::Analysis::touch
void touch()
Observable analysis information changed: records curr_mut() as dirty - the seed set of the next spars...
Definition
phase.h:253
mim::Analysis::world
World & world()
Definition
phase.h:58
mim::App
Definition
lam.h:215
mim::Axm::isa
static auto isa(const Def *def)
Definition
axm.h:112
mim::Def
Base class for all Defs.
Definition
def.h:289
mim::Def::type
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition
def.h:1119
mim::Extract
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition
tuple.h:360
mim::Lam
A function.
Definition
lam.h:91
mim::Pi::isa_cn
static const Pi * isa_cn(const Def *d)
Definition
lam.h:50
mim::World
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition
world.h:43
mim::plug::mem::EscapeAnalysis::rewrite_imm_App
const Def * rewrite_imm_App(const App *) override
Definition
escape_analysis.cpp:52
mim::plug::mem::EscapeAnalysis::allocates
static bool allocates(const App *app)
Definition
escape_analysis.h:39
mim::plug::mem::EscapeAnalysis::Chain::last
DefMap< size_t > last
Per allocation the ops mention: the index of the last op that does so.
Definition
escape_analysis.h:32
mim::plug::mem::EscapeAnalysis::confined
bool confined(const Def *alloc) const
Is the local alloc only mentioned on its home's own memory chain?
Definition
escape_analysis.h:48
mim::plug::mem::EscapeAnalysis::EscapeAnalysis
EscapeAnalysis(World &world)
Definition
escape_analysis.h:36
mim::plug::mem::EscapeAnalysis::freed
bool freed(const Def *alloc) const
Does a mem.free release alloc?
Definition
escape_analysis.h:50
mim::plug::mem::EscapeAnalysis::Chain::ops
fe::Vector< const App * > ops
The ops threading the memory from the Lam's Var to its tail, in program order.
Definition
escape_analysis.h:31
mim::plug::mem::EscapeAnalysis::Chain::tail
const App * tail
Definition
escape_analysis.h:30
mim::plug::mem::EscapeAnalysis::chains
const LamMap< Chain > & chains() const
Definition
escape_analysis.h:44
mim::plug::mem::EscapeAnalysis::leave
void leave() override
Called after curr_mut() has been completely dealt with.
Definition
escape_analysis.cpp:57
mim::plug::mem::EscapeAnalysis::Chain::targets
DefVec targets
The continuations the tail transfers control to.
Definition
escape_analysis.h:33
mim::plug::mem::EscapeAnalysis::escaping
bool escaping(Lam *lam) const
May lam run at any time, as it is used as a value or jumped to by an escaping Lam?
Definition
escape_analysis.h:46
mim::plug::mem::EscapeAnalysis::freed_alloc
static const App * freed_alloc(const Def *def)
The allocation def releases if it is a mem.free of one; nullptr otherwise.
Definition
escape_analysis.h:52
mim::plug::mem::EscapeAnalysis::rewrite_imm
const Def * rewrite_imm(const Def *) override
Records what each value may carry: the allocations it aliases and the nested Lams in it.
Definition
escape_analysis.cpp:18
mim::plug::mem::EscapeAnalysis::Chain
Definition
escape_analysis.h:29
mem.h
mim::plug::mem
The mem Plugin
Definition
escape_analysis.h:9
mim::plug::mem::free
free
Definition
autogen.h:84
mim::plug::mem::alloc
alloc
Definition
autogen.h:63
mim
Definition
ast.h:16
mim::LamSet
GIDSet< Lam * > LamSet
Definition
lam.h:211
mim::DefMap
GIDMap< const Def *, To > DefMap
Definition
def.h:93
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
phase.h
include
mim
plug
mem
escape_analysis.h
Generated by
1.18.0