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