MimIR
0.5-dev
MimIR is my Intermediate Representation
Toggle main menu visibility
Loading...
Searching...
No Matches
lower_index.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <cstdint>
4
5
#include <optional>
6
7
#include <
mim/phase.h
>
8
9
namespace
mim::plug::affine::phase
{
10
11
/// Lowers the affine index algebra to core arithmetic.
12
///
13
/// The opaque affine.Index type is rewritten to the wide `Idx 0` (i64) carrier, and the index operations are computed
14
/// with wrap-around (`core.Mode::none`) arithmetic, so negation/subtraction are correct via two's complement:
15
/// * `affine.lit n` ↦ `n` reinterpreted as an `Idx 0`,
16
/// * `affine.op.add (a, b)` ↦ `core.wrap.add none (a, b)`,
17
/// * `affine.op.sub (a, b)` ↦ `core.wrap.sub none (a, b)`,
18
/// * `affine.op.neg a` ↦ `core.wrap.sub none (0, a)`,
19
/// * `affine.semiop.mul (a, c)` ↦ `core.wrap.mul none (a, c)`.
20
///
21
/// The `affine.map f idxs mem` bridge lowers to: widen each runtime `idxs#i : Idx (sin#i)` to `Idx 0` via
22
/// `core.conv.u`, apply the (now core-arithmetic) function `f`, and
23
/// narrow each result back to its target `Idx (sout#j)` via `core.conv.u`.
24
///
25
/// The division-based semiops (`ceildiv`, `floordiv`, `rem`) lower to `core.div`, which threads a `mem.M`. The mem is
26
/// taken from the enclosing `affine.map`'s mem operand (tracked in #mem_), advanced through the div chain, and
27
/// returned alongside the result.
28
class
LowerIndex
:
public
RWPhase
{
29
public
:
30
using
RWPhase::RWPhase
;
31
32
const
Def
*
rewrite
(
const
Def
*)
final
;
33
const
Def
*
rewrite_imm_App
(
const
App
*)
final
;
34
35
private
:
36
/// Inclusive range of the values a lowered `Idx 0` expression can take, proven not to wrap.
37
struct
Range {
38
int64_t lo, hi;
39
};
40
41
/// The body sees every index as a bare `Idx 0`, so this is the only place the domain is still known.
42
struct
Domain {
43
const
Def
* idxs =
nullptr
;
44
fe::Vector<std::optional<int64_t>> extents;
45
};
46
47
/// The addends of an expression that are multiples of `c`, and whether the rest can carry into a division by it.
48
struct
Split {
49
DefVec
even, rest;
50
bool
carries;
51
};
52
53
/// `x = q·k + r` with `0 ≤ r < k` for a proper divisor `k` of the divisor at hand.
54
struct
Peel {
55
const
Def
*q, *r;
56
int64_t k;
57
};
58
59
std::optional<Range> range_of(
const
Def
*)
const
;
60
Split split(
const
Def
*, int64_t);
61
std::optional<Peel> peel(
const
Def
*, int64_t);
62
const
Def
* fold_udiv(
const
Def
*, int64_t);
63
const
Def
* fold_urem(
const
Def
*, int64_t);
64
const
Def
* udiv(
const
Def
*,
const
Def
*);
65
const
Def
* urem(
const
Def
*,
const
Def
*);
66
67
const
Def
* mem_ =
nullptr
;
68
Domain dom_;
69
70
/// Rewritten access-map lams, keyed by `f` and then `sin`: shared annex lams like `tensor.proj_map` are reached
71
/// from `affine.map`s over different domains, and a fold only holds for the extents that justified it.
72
DefMap<DefMap<Lam*>
> specialized_;
73
DefMap<Lam*>
etas_;
74
};
75
76
}
// namespace mim::plug::affine::phase
mim::App
Definition
lam.h:215
mim::Def
Base class for all Defs.
Definition
def.h:289
mim::RWPhase::RWPhase
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition
phase.h:334
mim::plug::affine::phase::LowerIndex
Lowers the affine index algebra to core arithmetic.
Definition
lower_index.h:28
mim::plug::affine::phase::LowerIndex::rewrite_imm_App
const Def * rewrite_imm_App(const App *) final
Definition
lower_index.cpp:257
mim::plug::affine::phase::LowerIndex::RWPhase
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition
phase.h:334
mim::plug::affine::phase::LowerIndex::rewrite
const Def * rewrite(const Def *) final
Definition
lower_index.cpp:251
mim::plug::affine::phase
Definition
lower_for.h:5
mim::DefMap
GIDMap< const Def *, To > DefMap
Definition
def.h:93
mim::DefVec
fe::Vector< const Def * > DefVec
Definition
def.h:98
phase.h
include
mim
plug
affine
phase
lower_index.h
Generated by
1.18.0