MimIR
0.4-dev
MimIR is my Intermediate Representation
Toggle main menu visibility
Loading...
Searching...
No Matches
eta_conv.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <fe/assert.h>
4
5
#include "
mim/phase.h
"
6
7
#include "
mim/util/gid.h
"
8
9
namespace
mim
{
10
11
/// Combined η-normalization: folds η-reduction and η-expansion into a single, idempotent phase.
12
/// A Lam should appear either **only** in callee position (Known) or not (Unknown).
13
/// A Lam that occurs in an unknown position more than once (Unknown_N) or in both positions (Both) is η-expanded
14
/// (`g f -> g (λx.f x)`); a genuine η-redex `λx.f x` whose `f` does **not** want to be expanded is η-reduced.
15
///
16
/// The analysis is **wrapper-transparent**: a use of a wrapper `λx.f x` is counted as a use of `f` at the same
17
/// position/multiplicity instead of counting `f` as Known (the wrapper's callee).
18
/// This makes `f`'s classification identical whether `f` is bare or wrapped, so the canonical η-form is a genuine
19
/// fixed point - the phase does not fight itself and can share one big `compile.phases tt` fixed-point loop with
20
/// BetaRed and mem.seo without oscillating.
21
class
EtaConv
:
public
InplaceRWPhase
{
22
public
:
23
EtaConv
(
World
&
world
)
24
:
InplaceRWPhase
(
world
,
"EtaConv"
) {}
25
EtaConv
(
World
&
world
,
flags_t
annex
)
26
:
InplaceRWPhase
(
world
,
annex
) {}
27
28
private
:
29
enum
Lattice :
u8
{
30
None = 0,
31
Known = 1,
32
Unknown_1 = 2,
33
Unknown_N = 3,
34
Both = 4,
35
};
36
37
static
Lattice join(Lattice l1, Lattice l2) {
38
if
(l1 == Unknown_1 && l2 == Unknown_1)
return
Unknown_N;
39
if
(l1 == l2)
return
l1;
40
if
(l1 == None)
return
l2;
41
if
(l2 == None)
return
l1;
42
if
(l1 == Both || l2 == Both)
return
Both;
43
if
(l1 == Known && (l2 == Unknown_1 || l2 == Unknown_N))
return
Both;
44
if
(l2 == Known && (l1 == Unknown_1 || l1 == Unknown_N))
return
Both;
45
if
(l1 == Unknown_1 && l2 == Unknown_N)
return
Unknown_N;
46
if
(l2 == Unknown_1 && l1 == Unknown_N)
return
Unknown_N;
47
fe::unreachable();
48
}
49
50
Lattice lattice(
const
Lam* lam) {
51
if
(
auto
i = lam2lattice_.find(lam); i != lam2lattice_.end())
return
i->second;
52
return
None;
53
}
54
55
static
bool
eta_expand(Lattice l) {
return
l
!= Known &&
l
!= Unknown_1 &&
l
!= None; }
56
bool
eta_expand(
const
Lam* lam) {
return
eta_expand(lattice(lam)); }
57
58
/// Should a wrapper `λx.f x` be kept (because `f` wants to be expanded) instead of reduced?
59
bool
keep_wrapper(
const
Def* f) {
60
auto
lam =
f
->isa<
Lam
>();
61
return
lam && eta_expand(lattice(lam));
62
}
63
64
/// Is @p lam a wrapper that is already in the shape a fresh Lam::eta_expand would produce here?
65
/// That means: it belongs to this one occurrence alone and carries the canonical `tt` filter.
66
/// Only then may we keep it - re-creating it would hand out a fresh identity on every run, so this phase would
67
/// never reach a fixed point in place.
68
bool
is_canonical_wrapper(
const
Lam* lam)
const
{
69
auto
i = wrapper_uses_.find(lam);
70
return
i != wrapper_uses_.end() && i->second == 1 && lam->filter() == lam->world().lit_tt();
71
}
72
73
void
join(
const
Lam* lam, Lattice l) {
74
if
(
auto
[i, ins] = lam2lattice_.emplace(lam, l); !ins) i->second = join(i->second, l);
75
}
76
77
bool
analyze
() final;
78
void
analyze
(const Def*);
79
void
visit(const Def*, Lattice);
80
81
/// An annex or external must keep its shape: neither η-reduce nor η-expand a root.
82
const
Def
*
rewrite_root
(const
Def
* def) final {
return
rewrite_no_eta(def); }
83
const
Def
*
rewrite
(
const
Def
*)
final
;
84
const
Def
*
rewrite_imm_App
(
const
App
*)
final
;
85
const
Def
*
rewrite_imm_Var
(
const
Var
*)
final
;
86
/// η-reduce wrappers but never η-expand - used for callee (Known) positions, where expansion must not happen
87
/// but a wrapper `λx.f x` should still collapse to `f` (just as the standalone EtaRed did everywhere).
88
const
Def
* rewrite_no_exp(
const
Def
* old_def);
89
const
Def
* rewrite_no_eta(
const
Def
* old_def) {
return
Rewriter::rewrite
(old_def); }
90
91
DefSet
analyzed_;
92
GIDMap<const Lam*, Lattice>
lam2lattice_;
93
GIDMap<const Lam*, u32>
wrapper_uses_;
///< How many occurrences does a wrapper `λx.f x` serve?
94
};
95
96
}
// namespace mim
mim::App
Definition
lam.h:224
mim::Def
Base class for all Defs.
Definition
def.h:273
mim::EtaConv::EtaConv
EtaConv(World &world)
Definition
eta_conv.h:23
mim::EtaConv::rewrite_imm_Var
const Def * rewrite_imm_Var(const Var *) final
Definition
eta_conv.cpp:83
mim::EtaConv::rewrite
const Def * rewrite(const Def *) final
Definition
eta_conv.cpp:37
mim::EtaConv::rewrite_imm_App
const Def * rewrite_imm_App(const App *) final
Definition
eta_conv.cpp:78
mim::EtaConv::EtaConv
EtaConv(World &world, flags_t annex)
Definition
eta_conv.h:25
mim::EtaConv::analyze
bool analyze() final
Runs the optional pre-analysis on Phase::world, typically to a fixed point, before rewriting begins.
Definition
eta_conv.cpp:5
mim::EtaConv::rewrite_root
const Def * rewrite_root(const Def *def) final
An annex or external must keep its shape: neither η-reduce nor η-expand a root.
Definition
eta_conv.h:82
mim::InplaceRWPhase::InplaceRWPhase
InplaceRWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition
phase.h:489
mim::InplaceRWPhase::world
World & world()
Definition
phase.h:77
mim::Phase::annex
flags_t annex() const
Definition
phase.h:81
mim::Rewriter::rewrite
virtual const Def * rewrite(const Def *)
Definition
rewrite.cpp:55
mim::Var
A variable introduced by a binder (mutable).
Definition
def.h:825
mim::World
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition
world.h:40
gid.h
mim::plug::core::ncmp::l
@ l
Definition
autogen.h:35
mim::plug::core::ncmp::f
@ f
Definition
autogen.h:31
mim
Definition
ast.h:16
mim::flags_t
u64 flags_t
Definition
types.h:39
mim::GIDMap
absl::flat_hash_map< K, V, GIDHash< K > > GIDMap
Definition
gid.h:24
mim::DefSet
GIDSet< const Def * > DefSet
Definition
def.h:89
mim::u8
uint8_t u8
Definition
types.h:27
mim::Node::Lam
@ Lam
Definition
def.h:122
phase.h
include
mim
phase
eta_conv.h
Generated by
1.18.0