MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
normalizers.cpp
Go to the documentation of this file.
1#include <mim/axm.h>
2#include <mim/world.h>
3
6#include <mim/plug/mem/mem.h>
7
9
10namespace mim::plug::autodiff {
11
12/// Currently this normalizer does nothin.
13/// TODO: Maybe we want to handle trivial lookup replacements here.
14const Def* normalize_ad(const Def*, const Def*, const Def*) { return {}; }
15
16const Def* normalize_AD(const Def*, const Def*, const Def* arg) {
17 auto ad_ty = autodiff_type_fun(arg);
18 if (ad_ty) return ad_ty;
19 return {};
20}
21
22const Def* normalize_Tangent(const Def*, const Def*, const Def* arg) { return tangent_type_fun(arg); }
23
24/// Currently this normalizer does nothing.
25/// We usually want to keep zeros as long as possible to avoid unnecessary allocations.
26/// A high-level addition with zero can be shortened directly.
27const Def* normalize_zero(const Def*, const Def*, const Def*) { return {}; }
28
29/// Currently resolved the full addition.
30/// There is no benefit in keeping additions around longer than necessary.
31const Def* normalize_add(const Def* type, const Def* callee, const Def* arg) {
32 auto& world = type->world();
33
34 // TODO: add tuple -> tuple of adds
35 // TODO: add zero -> other
36 // TODO: unify mapping over structure with other aspects like zero
37
38 auto T = callee->as<App>()->arg();
39 auto [a, b] = arg->projs<2>();
40
41 if (Axm::isa<zero>(a)) return b;
42 if (Axm::isa<zero>(b)) return a;
43 // A value level match would be harder as a tuple might in reality be a var or extract
44 if (auto sig = T->isa<Sigma>()) {
45 auto p = sig->num_ops(); // TODO: or num_projs
46 auto ops = DefVec(p, [&](size_t i) {
47 return world.app(world.app(world.annex<add>(), sig->op(i)), {a->proj(p, i), b->proj(p, i)});
48 });
49 return world.tuple(ops);
50 } else if (auto arr = T->isa<Arr>()) {
51 // TODO: is this working for non-lit (non-tuple) or do we need a loop?
52 auto pack = world.mut_pack(T)->set_shape(*arr->shape());
53 auto body_type = arr->body();
54 pack->set_body(world.app(world.app(world.annex<add>(), body_type),
55 {world.extract(a, pack->var()), world.extract(b, pack->var())}));
56 return pack;
57 } else if (Idx::isa(type)) {
58 return world.call(core::wrap::add, 0_n, Defs{a, b});
59 } else if (Axm::isa<mem::M>(type)) {
60 // TODO: mem stays here (only resolved after direct simplification)
61 return {};
62 } else if (Axm::isa<math::F>(T)) {
63 return world.call(math::arith::add, 0_n, Defs{a, b});
64 }
65
66 return {};
67}
68
69const Def* normalize_sum(const Def* type, const Def* callee, const Def* arg) {
70 auto& world = type->world();
71
72 auto [count, T] = callee->as<App>()->args<2>();
73
74 if (auto lit = count->isa<Lit>()) {
75 auto val = lit->get<nat_t>();
76 auto args = arg->projs(val);
77 auto sum = world.app(world.annex<zero>(), T);
78 // This special case would also be handled by add zero
79 if (val >= 1) sum = args[0];
80 for (size_t i = 1; i < val; ++i)
81 sum = world.app(world.app(world.annex<add>(), T), {sum, args[i]});
82 return sum;
83 }
84 return {};
85}
86
88
89} // namespace mim::plug::autodiff
#define MIM_autodiff_NORMALIZER_IMPL
Definition autogen.h:86
A (possibly paramterized) Array.
Definition tuple.h:305
static auto isa(const Def *def)
Definition axm.h:112
Base class for all Defs.
Definition def.h:289
auto projs(Projector auto f) const
Splits this Def via Def::projections into an Array (if A == std::dynamic_extent) or std::array (other...
Definition def.h:457
static const Def * isa(const Def *def)
Checks if def is a Idx s and returns s or nullptr otherwise.
Definition def.cpp:670
A dependent tuple type.
Definition tuple.h:39
The automatic differentiation Plugin
Definition autodiff.h:7
const Def * normalize_Tangent(const Def *, const Def *, const Def *arg)
const Def * normalize_add(const Def *type, const Def *callee, const Def *arg)
Currently resolved the full addition.
const Def * autodiff_type_fun(const Def *)
Definition autodiff.cpp:107
const Def * normalize_AD(const Def *, const Def *, const Def *arg)
const Def * normalize_ad(const Def *, const Def *, const Def *)
Currently this normalizer does nothin.
const Def * tangent_type_fun(const Def *)
Definition autodiff.cpp:56
const Def * normalize_sum(const Def *type, const Def *callee, const Def *arg)
const Def * normalize_zero(const Def *, const Def *, const Def *)
Currently this normalizer does nothing.
u64 nat_t
Definition types.h:37
fe::View< const Def * > Defs
Definition def.h:96
fe::Vector< const Def * > DefVec
Definition def.h:98