MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
lower_ptr.cpp
Go to the documentation of this file.
2
3#include <mim/axm.h>
4#include <mim/def.h>
5
6#include <mim/plug/gpu/gpu.h>
7#include <mim/plug/mem/mem.h>
8
10
11namespace mim::plug::buffer {
12
13namespace {
14
15/// Successively offsets `ptr` by each component of the index `tuple`, peeling one array dimension per `mem.lea`.
16const Def* op_lea_tuple(const Def* ptr, const Def* tuple) {
17 auto n = tuple->num_projs();
18 auto element = ptr;
19 for (size_t i = 0; i < n; ++i)
20 element = mem::op_lea(element, tuple->proj(n, i));
21 return element;
22}
23
24/// Builds the nested array type `«s; T»` from a shape tuple `s` and element type `T`.
25const Def* arr_ty_of(const Def* s, const Def* T) {
26 auto& w = s->world();
27 auto n = s->num_projs();
28 auto arr_ty = T;
29 for (int i = (int)n - 1; i >= 0; --i)
30 arr_ty = w.arr(s->proj(n, i), arr_ty);
31 return arr_ty;
32}
33
34/// Builds the nested `pack` `‹s; val›` replicating `val` across every element.
35const Def* pack_tuple(const Def* s, const Def* val) {
36 auto& w = val->world();
37 auto n = s->num_projs();
38 auto element = val;
39 for (int i = (int)n - 1; i >= 0; --i)
40 element = w.pack(s->proj(n, i), element);
41 return element;
42}
43
44} // namespace
45
46const Def* LowerPtr::rewrite_imm_App(const App* app) {
47 if (is_bootstrapping()) return RWPhase::rewrite_imm_App(app);
48 auto& w = new_world();
49
50 if (auto buf_ax = Axm::isa<buffer::Buf>(app)) {
51 auto [r, s, T] = buf_ax->args<3>();
52 s = rewrite(s);
53 T = rewrite(T);
54 return w.call<mem::Ptr>(Defs{arr_ty_of(s, T), w.lit_nat_0()});
55 } else if (auto alloc_ax = Axm::isa<buffer::alloc>(app)) {
56 auto mem = rewrite(alloc_ax->arg());
57 auto [r, s, T] = alloc_ax->callee()->as<App>()->args<3>();
58 s = rewrite(s);
59 T = rewrite(T);
60 auto [mem2, ptr] = mem::op_alloc(arr_ty_of(s, T), mem)->projs<2>();
61 return w.tuple({mem2, ptr});
62 } else if (auto read_ax = Axm::isa<buffer::read>(app)) {
63 auto [mem, buf, idx] = read_ax->args<3>();
64 mem = rewrite(mem);
65 buf = rewrite(buf);
66 idx = rewrite(idx);
67 auto element_ptr = op_lea_tuple(buf, idx);
68 auto [mem2, val] = w.call<mem::load>(Defs{mem, element_ptr})->projs<2>();
69 return w.tuple({mem2, val});
70 } else if (auto write_ax = Axm::isa<buffer::write>(app)) {
71 auto [mem, buf, idx, val] = write_ax->args<4>();
72 mem = rewrite(mem);
73 buf = rewrite(buf);
74 idx = rewrite(idx);
75 val = rewrite(val);
76 auto element_ptr = op_lea_tuple(buf, idx);
77 auto mem2 = w.call<mem::store>(Defs{mem, element_ptr, val});
78 return w.tuple({mem2, buf});
79 } else if (auto copy_ax = Axm::isa<buffer::copy>(app)) {
80 auto [mem, dst, src] = copy_ax->args<3>();
81 mem = rewrite(mem);
82 dst = rewrite(dst);
83 src = rewrite(src);
84 // Whole-buffer copy: load the entire array out of `src` and store it into `dst`.
85 auto [mem2, val] = w.call<mem::load>(Defs{mem, src})->projs<2>();
86 return w.call<mem::store>(Defs{mem2, dst, val});
87 } else if (auto init_ax = Axm::isa<buffer::init>(app)) {
88 auto [mem, val] = init_ax->args<2>();
89 auto [r, s, T] = init_ax->callee()->as<App>()->args<3>();
90 mem = rewrite(mem);
91 val = rewrite(val);
92 s = rewrite(s);
93 T = rewrite(T);
94 auto [mem2, ptr] = mem::op_alloc(arr_ty_of(s, T), mem)->projs<2>();
95 auto mem3 = w.call<mem::store>(Defs{mem2, ptr, val});
96 return w.tuple({mem3, ptr});
97 } else if (auto const_ax = Axm::isa<buffer::lit>(app)) {
98 auto [mem, val] = const_ax->args<2>();
99 auto [r, s, T] = const_ax->callee()->as<App>()->args<3>();
100 mem = rewrite(mem);
101 val = rewrite(val);
102 s = rewrite(s);
103 T = rewrite(T);
104 auto [mem2, ptr] = mem::op_alloc(arr_ty_of(s, T), mem)->projs<2>();
105 auto mem3 = w.call<mem::store>(Defs{mem2, ptr, pack_tuple(s, val)});
106 return w.tuple({mem3, ptr});
107 } else if (auto buf_alloc_copy = Axm::isa<gpu::buf_alloc_copy>(app)) {
108 auto m0 = rewrite(buf_alloc_copy->arg(0));
109 auto m1 = rewrite(buf_alloc_copy->arg(1));
110 auto ptr = rewrite(buf_alloc_copy->arg(2));
111 return w.call(gpu::alloc_copy::block, w.tuple({m0, m1, ptr}));
112 } else if (auto buf_copy_to_host = Axm::isa<gpu::buf_copy_to_host>(app)) {
113 auto m0 = rewrite(buf_copy_to_host->arg(0));
114 auto m1 = rewrite(buf_copy_to_host->arg(1));
115 auto d_ptr = rewrite(buf_copy_to_host->arg(2));
116 auto h_ptr = rewrite(buf_copy_to_host->arg(3));
117 return w.call(gpu::copy_to_host::block, w.tuple({m0, m1, d_ptr, h_ptr}));
118 }
119
120 return RWPhase::rewrite_imm_App(app);
121}
122
123} // namespace mim::plug::buffer
static auto isa(const Def *def)
Definition axm.h:112
Base class for all Defs.
Definition def.h:273
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:440
const fe::Vector< std::string > & args()
Command-line arguments passed to this Phase's plugin via -X <plugin>:<arg>.
Definition phase.cpp:23
bool is_bootstrapping() const
Returns whether we are currently bootstrapping (rewriting annexes).
Definition phase.h:403
World & new_world()
Create new Defs into this.
Definition phase.h:452
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:55
const Def * rewrite_imm_App(const App *) override
Definition lower_ptr.cpp:46
The buffer Plugin
Definition buffer.h:7
The mem Plugin
Definition mem.h:11
const Def * op_lea(const Def *ptr, const Def *index)
Definition mem.h:112
const Def * op_alloc(const Def *type, const Def *as, const Def *mem)
Definition mem.h:129
fe::View< const Def * > Defs
Definition def.h:91