Files
triton/lib/codegen/analysis/allocation.cc

108 lines
2.8 KiB
C++
Raw Normal View History

#include <algorithm>
#include <climits>
2019-10-11 19:05:54 -04:00
#include "triton/codegen/analysis/layout.h"
#include "triton/codegen/analysis/allocation.h"
#include "triton/codegen/analysis/liveness.h"
#include "triton/ir/utils.h"
2019-01-07 22:49:37 -05:00
namespace triton{
2019-01-07 22:49:37 -05:00
namespace codegen{
namespace analysis{
2019-01-07 22:49:37 -05:00
void allocation::run(ir::module &mod) {
2019-01-07 22:49:37 -05:00
using std::max;
using std::min;
typedef std::multimap<unsigned, segment> triples_map_type;
2019-10-11 19:05:54 -04:00
std::vector<layout_t*> I;
2019-10-12 01:25:08 -04:00
for(auto x: liveness_->get())
2019-01-07 22:49:37 -05:00
I.push_back(x.first);
2019-10-11 19:05:54 -04:00
std::vector<layout_t*> J = I;
2019-01-07 22:49:37 -05:00
triples_map_type H;
H.insert({0, segment{0, INT_MAX}});
2019-01-07 22:49:37 -05:00
2019-10-11 19:05:54 -04:00
std::vector<layout_t*> V;
std::map<layout_t*, unsigned> starts;
2019-01-07 22:49:37 -05:00
while(!J.empty()){
auto h_it = H.begin();
unsigned w = h_it->first;
segment xh = h_it->second;
H.erase(h_it);
2019-10-11 19:05:54 -04:00
auto j_it = std::find_if(J.begin(), J.end(), [&](layout_t* JJ){
2019-10-12 01:25:08 -04:00
segment xj = liveness_->get(JJ);
2019-01-07 22:49:37 -05:00
bool res = xj.intersect(xh);
for(auto val: H)
res = res && !val.second.intersect(xj);
return res;
});
if(j_it != J.end()){
2019-09-27 22:15:30 -04:00
unsigned size = (*j_it)->size;
2019-10-12 01:25:08 -04:00
segment xj = liveness_->get(*j_it);
2019-01-07 22:49:37 -05:00
starts[*j_it] = w;
H.insert({w + size, segment{max(xh.start, xj.start), min(xh.end, xj.end)}});
if(xh.start < xj.start)
H.insert({w, segment{xh.start, xj.end}});
if(xj.end < xh.end)
H.insert({w, segment{xj.start, xh.end}});
V.push_back(*j_it);
J.erase(j_it);
}
}
// Build interference graph
2019-10-11 19:05:54 -04:00
std::map<layout_t*, std::set<layout_t*>> interferences;
for(layout_t* x: V)
for(layout_t* y: V){
2019-09-27 22:15:30 -04:00
if(x->id == y->id)
2019-01-07 22:49:37 -05:00
continue;
unsigned X0 = starts[x], Y0 = starts[y];
2019-09-27 22:15:30 -04:00
unsigned NX = x->size;
unsigned NY = y->size;
2019-01-07 22:49:37 -05:00
segment XS = {X0, X0 + NX};
segment YS = {Y0, Y0 + NY};
2019-10-12 01:25:08 -04:00
if(liveness_->get(x).intersect(liveness_->get(y))
2019-01-07 22:49:37 -05:00
&& XS.intersect(YS))
interferences[x].insert(y);
}
// Initialize colors
2019-10-11 19:05:54 -04:00
std::map<layout_t*, int> colors;
for(layout_t* X: V)
2019-09-27 22:15:30 -04:00
colors[X] = (X->id==V[0]->id)?0:-1;
2019-01-07 22:49:37 -05:00
// First-fit graph coloring
2019-01-07 22:49:37 -05:00
std::vector<bool> available(V.size());
2019-10-11 19:05:54 -04:00
for(layout_t* x: V){
2019-01-07 22:49:37 -05:00
// Non-neighboring colors are available
std::fill(available.begin(), available.end(), true);
2019-10-11 19:05:54 -04:00
for(layout_t* Y: interferences[x]){
2019-01-07 22:49:37 -05:00
int color = colors[Y];
if(color >= 0)
available[color] = false;
}
// Assigns first available color
auto It = std::find(available.begin(), available.end(), true);
colors[x] = std::distance(available.begin(), It);
}
// Finalize allocation
2019-10-11 19:05:54 -04:00
for(layout_t* x: V){
2019-01-07 22:49:37 -05:00
unsigned Adj = 0;
2019-10-11 19:05:54 -04:00
for(layout_t* y: interferences[x])
2019-09-27 22:15:30 -04:00
Adj = std::max<unsigned>(Adj, starts[y] + y->size);
offsets_[x] = starts[x] + colors[x] * Adj;
2019-01-07 22:49:37 -05:00
}
// Save maximum size of induced memory space
allocated_size_ = 0;
2019-10-11 19:05:54 -04:00
for(layout_t* x: V)
2019-09-27 22:15:30 -04:00
allocated_size_ = std::max<size_t>(allocated_size_, starts[x] + x->size);
2019-01-07 22:49:37 -05:00
}
}
}
}