docc 0.8.3 (0d44999b)
C++ API Reference
Loading...
Searching...
No Matches
memory_layout_analysis.h
Go to the documentation of this file.
1
8
9#pragma once
10
11#include <functional>
12#include <map>
13#include <optional>
14#include <set>
15#include <unordered_map>
16#include <unordered_set>
17#include <utility>
18#include <vector>
19
20#include <string>
21
29
30namespace sdfg {
31namespace analysis {
32
34
35struct MemoryTile {
36 std::string container; // Container name
37 data_flow::Subset min_subset; // Minimum accessed indices in this tile
38 data_flow::Subset max_subset; // Maximum accessed indices (empty for point tiles: max == min)
39 MemoryLayout layout; // Inferred tile layout at this loop level
40 bool first_dim_bounded; // True if first dimension is bounded (Tensor/Array), false for unbounded pointers
41
42 // A pre-ranged access already spans its full accessed region in [min_subset,
43 // max_subset] (e.g. a library-node operand whose offset was partitioned into
44 // per-dimension bases). During merge its min gets only a lower bound and its
45 // max only an upper bound. A point access (false) samples a single index that
46 // must be swept over its own symbols' ranges, so both bounds apply to it.
47 bool pre_ranged = false;
48
51 bool is_point() const;
52
56 return max_subset.empty() ? min_subset : max_subset;
57 }
58
64
69
75 std::pair<symbolic::Expression, symbolic::Expression> contiguous_range() const;
76};
77
79 MemoryTile tile; // Bounding box for this group
80 std::vector<const data_flow::Memlet*> memlets; // Memlets belonging to this group
81};
82
96private:
97 std::unordered_map<const data_flow::Memlet*, MemoryTile> accesses_;
98 // Per node, the memlets in its subtree whose accesses are recorded, and the nodes whose tiles are up to date.
99 // Queries compute a scope that is not, from its children that are not either: after a local invalidation, only
100 // what is queried is computed again.
101 std::unordered_map<const structured_control_flow::ControlFlowNode*, std::vector<const data_flow::Memlet*>>
102 scope_memlets_;
103 std::unordered_set<const structured_control_flow::ControlFlowNode*> computed_;
104 analysis::AnalysisManager* analysis_manager_ = nullptr;
105 std::map<std::pair<const structured_control_flow::ControlFlowNode*, std::string>, MemoryTile> tiles_;
106 std::map<std::pair<const structured_control_flow::ControlFlowNode*, std::string>, std::vector<MemoryTileGroup>>
107 tile_groups_;
108
109 // Owned, branch-condition-aware `AssumptionsAnalysis` instance. The
110 // manager-cached AA is kept cheap and does NOT refine branch
111 // assumptions; MLA's per-scope tile inference must see the refined
112 // halo-style coupled constraints emitted at IfElse guards, so it owns
113 // its own instance rebuilt on every `run()`.
114 std::unique_ptr<AssumptionsAnalysis> detailed_assumptions_;
115
116 // Per-run bounds/proof caches, shared by all blocks with the same assumption set.
117 std::unordered_map<const symbolic::Assumptions*, std::unique_ptr<symbolic::AssumptionsBounds>> bounds_cache_;
118
119 void traverse(structured_control_flow::ControlFlowNode& node, analysis::AnalysisManager& analysis_manager);
120
122 void ensure(const structured_control_flow::ControlFlowNode& scope) const;
123
124 void process_block(structured_control_flow::Block& block, analysis::AnalysisManager& analysis_manager);
125
126 void record_access(const data_flow::Memlet& memlet, MemoryTile access);
127
128 void merge_scope_layouts(
130 const std::vector<const data_flow::Memlet*>& memlets,
131 analysis::AnalysisManager& analysis_manager
132 );
133
134 void compute_tile_groups(
136 const std::string& container,
137 const std::vector<const data_flow::Memlet*>& memlets,
138 const MemoryLayout& reference_layout,
139 size_t ndims,
140 symbolic::BoundAnalysis& ba_tight,
141 symbolic::BoundAnalysis& ba_loose,
142 const std::function<bool(const symbolic::Expression&)>& bounds_are_sound
143 );
144
145protected:
146 void run(analysis::AnalysisManager& analysis_manager) override;
147
148public:
151
152 std::string name() const override {
153 return "MemoryLayoutAnalysis";
154 }
155
158
164 const MemoryTile* access(const data_flow::Memlet& memlet) const;
165
172 const MemoryTile* tile(const structured_control_flow::ControlFlowNode& scope, const std::string& container) const;
173
180 const std::vector<MemoryTileGroup>*
181 tile_groups(const structured_control_flow::ControlFlowNode& scope, const std::string& container) const;
182
189 const MemoryTileGroup*
191};
192
193} // namespace analysis
194} // namespace sdfg
Definition options.h:56
Definition structured_sdfg.h:30
Definition analysis.h:53
Analysis(StructuredSDFG &sdfg)
const MemoryTile * tile(const structured_control_flow::ControlFlowNode &scope, const std::string &container) const
Get the inferred memory layout for a container at a specific scope.
MemoryLayoutAnalysis(StructuredSDFG &sdfg)
std::string name() const override
Definition memory_layout_analysis.h:152
const MemoryTileGroup * tile_group_for(const structured_control_flow::ControlFlowNode &scope, const data_flow::Memlet &memlet) const
Get the tile group containing a specific memlet at a scope.
const MemoryTile * access(const data_flow::Memlet &memlet) const
Get the inferred memory layout for a memlet.
void run(analysis::AnalysisManager &analysis_manager) override
bool invalidate(structured_control_flow::ControlFlowNode &changed) override
Marks the subtree of changed and the scopes around it as out of date; queries compute them again.
const std::vector< MemoryTileGroup > * tile_groups(const structured_control_flow::ControlFlowNode &scope, const std::string &container) const
Get tile groups for a container at a specific scope.
MemoryLayoutAnalysis(StructuredSDFG &sdfg, const Options &options)
Edge in the dataflow graph representing data movement.
Definition memlet.h:131
The metadata associated with a addressing a tensor in elements Meant to be used with TensorNodes to d...
Definition tensor_layout.h:20
A control flow node representing a basic block with dataflow computations.
Definition block.h:42
Base class for all structured control flow nodes in a StructuredSDFG.
Definition control_flow_node.h:44
Computes bounds of symbolic expressions using assumptions.
Definition extreme_values.h:110
Computing bounds of symbolic expressions using assumptions.
std::vector< Expression > MultiExpression
Vector of symbolic expressions for multi-dimensional operations.
Definition symbolic.h:89
SymEngine::RCP< const SymEngine::Basic > Expression
Reference-counted pointer to a symbolic expression (SymEngine Basic).
Definition symbolic.h:83
Edges in the dataflow graph representing data movement.
Definition analysis.h:8
math::tensor::TensorLayout MemoryLayout
Definition memory_layout_analysis.h:33
symbolic::MultiExpression Subset
Type alias for a subset specification (array of symbolic expressions).
Definition memlet.h:103
Definition analysis.h:7
Definition memory_layout_analysis.h:78
MemoryTile tile
Definition memory_layout_analysis.h:79
std::vector< const data_flow::Memlet * > memlets
Definition memory_layout_analysis.h:80
Definition memory_layout_analysis.h:35
std::pair< symbolic::Expression, symbolic::Expression > contiguous_range() const
First and last linear element addresses: offset + sum(stride[d] * idx[d]).
bool is_point() const
A trivial (point) tile: a single index per dimension (min == max), as opposed to a bounded range.
bool first_dim_bounded
Definition memory_layout_analysis.h:40
std::string container
Definition memory_layout_analysis.h:36
bool pre_ranged
Definition memory_layout_analysis.h:47
MemoryLayout layout
Definition memory_layout_analysis.h:39
symbolic::MultiExpression extents() const
Per-dimension bounding box extents: max[d] - min[d] + 1.
const data_flow::Subset & upper_subset() const
The upper index per dimension: max_subset, or min_subset for point tiles (which omit max_subset since...
Definition memory_layout_analysis.h:55
data_flow::Subset max_subset
Definition memory_layout_analysis.h:38
data_flow::Subset min_subset
Definition memory_layout_analysis.h:37
symbolic::MultiExpression extents_approx() const
Per-dimension extents with min/max resolved to upper bounds via overapproximation.
Symbolic system for integer-based symbol analysis.