MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
free_locals.h
Go to the documentation of this file.
1#pragma once
2
3#include <mim/nest.h>
4
6
7namespace mim::plug::mem::phase {
8
9/// Frees the memory a function allocates but does not let escape; see mem::EscapeAnalysis.
10///
11/// An allocation only its home's own memory chain mentions is freed right after its last use there.
12/// Any other is freed as control passes from where it is live to where it is dead.
13/// It is live on entry to a Nest node if the node or a sibling it or one of its ancestors reaches mentions it.
14/// Since a recursive node reaches itself, this covers loops, too.
15/// This is closed under control flow: once dead, an allocation stays dead.
16class FreeLocals : public RWPhase {
17public:
19 : RWPhase(world, annex, &escape_)
20 , escape_(world) {}
21
22private:
23 bool analyze() final;
24 const Def* rewrite_imm_App(const App*) final;
25
26 /// Collects the mentions of every node's subtree.
27 const DefSet& mentions(const Nest::Node*);
28 /// The mentions of every sibling @p node transitively reaches.
29 const DefSet& reach(const Nest::Node* node);
30 /// Places the frees of @p alloc in @p node%'s subtree, which hangs below its @p home.
31 void place(const Nest::Node* home, const Nest::Node* node, const Def* alloc);
32 bool live(const Nest::Node* home, const Nest::Node* node, const Def* alloc);
33 bool dead(const Nest::Node* home, const Def* target, const Def* alloc);
34
35 /// Rebuilds @p arg with `mem.free`s of the (old-world) @p allocs threaded through its memory @p mem.
36 const Def* thread(const Def* arg, const Def* mem, const DefVec& allocs);
37 /// Rebuilds a control position of a tail, freeing on the way to the targets in @p edges.
38 const Def* rewrite_target(const Def* target, const DefMap<DefVec>& edges);
39 /// A continuation that frees @p allocs and jumps on to @p cont.
40 const Def* trampoline(const Def* cont, const DefVec& allocs);
41 const Def* free(const Def* mem, const DefVec& allocs);
42
43 EscapeAnalysis escape_;
44 GIDMap<const Nest::Node*, DefSet> mentions_;
45 GIDMap<const Nest::Node*, DefSet> reach_;
46 /// Old op or tail ↦ allocations to free right before it.
47 DefMap<DefVec> frees_;
48 /// Old tail ↦ old target ↦ allocations to free on the way there.
49 DefMap<DefMap<DefVec>> edges_;
50};
51
52} // namespace mim::plug::mem::phase
Base class for all Defs.
Definition def.h:289
Builds a nesting tree for all mutables/binders.
Definition nest.h:25
flags_t annex() const
Definition phase.h:62
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition phase.h:334
World & world()=delete
Hides both and forbids direct access.
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:43
Determines which allocations stay within the scope that allocates them.
const Def * rewrite_imm_App(const App *) final
FreeLocals(World &world, flags_t annex)
Definition free_locals.h:18
bool analyze() final
Runs the optional pre-analysis on old_world(), typically to a fixed point, before rewriting begins.
The mem Plugin
ankerl::unordered_dense::map< K, V, GIDHash< K > > GIDMap
Definition gid.h:22
u64 flags_t
Definition types.h:39
GIDMap< const Def *, To > DefMap
Definition def.h:93
fe::Vector< const Def * > DefVec
Definition def.h:98
GIDSet< const Def * > DefSet
Definition def.h:94
Node
Definition def.h:123