finish preparations for coloring
This commit is contained in:
@ -150,3 +150,15 @@ bool GetCollectionsIsSame(const Container &a, const Container &b, Compare comp =
|
|||||||
}
|
}
|
||||||
|
|
||||||
CFGType BuildCFGForFunction(const std::shared_ptr<FunctionDefItem> &func);
|
CFGType BuildCFGForFunction(const std::shared_ptr<FunctionDefItem> &func);
|
||||||
|
|
||||||
|
// RISC-V calling convention compatible
|
||||||
|
const static std::vector<std::string> held_tmp_regs = {"x28", "x29", "x30", "x31"};
|
||||||
|
const static std::string zero = "x0", sp = "x2", ra = "x1", fp = "x8";
|
||||||
|
const static std::vector<std::string> callee_saved_regs = {"x3", "x4", "x9", "x18", "x19", "x20", "x21",
|
||||||
|
"x22", "x23", "x24", "x25", "x26", "x27"};
|
||||||
|
const static std::vector<std::string> caller_saved_regs = {"x5", "x6", "x7", "x10", "x11", "x12",
|
||||||
|
"x13", "x14", "x15", "x16", "x17"};
|
||||||
|
const static std::vector<std::string> arg_regs = {"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"};
|
||||||
|
const static std::vector<std::string> allocating_regs = {"x3", "x4", "x9", "x18", "x19", "x20", "x21", "x22",
|
||||||
|
"x23", "x24", "x25", "x26", "x27", "x5", "x6", "x7",
|
||||||
|
"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"};
|
@ -3,19 +3,32 @@
|
|||||||
#include "cfg.h"
|
#include "cfg.h"
|
||||||
class ConfGraphNode {
|
class ConfGraphNode {
|
||||||
public:
|
public:
|
||||||
std::string var_name;
|
const static size_t kInf = (std::numeric_limits<size_t>::max()) >> 2;
|
||||||
|
std::vector<size_t> var_ids;
|
||||||
size_t color;
|
size_t color;
|
||||||
bool is_move_related;
|
size_t degree;
|
||||||
bool move_related_but_frozen;
|
|
||||||
bool is_binded_with_physical_reg;
|
bool is_binded_with_physical_reg;
|
||||||
std::vector<ConfGraphNode *> neighbors;
|
std::list<ConfGraphNode *> neighbors;
|
||||||
ConfGraphNode(std::string var_name) : var_name(var_name) {}
|
std::list<opt::MoveInstruct *> move_neighbors;
|
||||||
|
ConfGraphNode() = default;
|
||||||
};
|
};
|
||||||
class ConfGraph {
|
class ConfGraph {
|
||||||
public:
|
public:
|
||||||
std::unordered_map<std::string, ConfGraphNode *> name_to_node;
|
// available after construction
|
||||||
|
std::unordered_map<size_t, ConfGraphNode *> id_to_node;
|
||||||
std::vector<std::shared_ptr<ConfGraphNode>> nodes;
|
std::vector<std::shared_ptr<ConfGraphNode>> nodes;
|
||||||
|
std::unordered_map<ConfGraphNode *, std::unordered_map<ConfGraphNode *, std::list<ConfGraphNode *>::iterator>>
|
||||||
|
adj_table;
|
||||||
|
|
||||||
|
// available during coloring
|
||||||
|
std::vector<ConfGraphNode *> stack;
|
||||||
|
std::vector<ConfGraphNode *> actual_spills;
|
||||||
|
std::unordered_set<ConfGraphNode *> low_degree_and_not_move_related;
|
||||||
|
std::unordered_set<ConfGraphNode *> low_degree_and_move_related;
|
||||||
|
std::unordered_set<ConfGraphNode *> high_degree_nodes;
|
||||||
|
std::unordered_set<opt::MoveInstruct *> pending_moves;
|
||||||
|
std::unordered_set<opt::MoveInstruct *> potential_moves;
|
||||||
};
|
};
|
||||||
|
|
||||||
ConfGraph BuildConfGraph(CFGType &cfg);
|
ConfGraph BuildConfGraph(CFGType &cfg);
|
||||||
bool TryColoring(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph& confgraph);
|
bool ConductColoring(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confgraph);
|
@ -1,6 +1,80 @@
|
|||||||
#include "confgraph.h"
|
#include "confgraph.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include "cfg.h"
|
#include "cfg.h"
|
||||||
|
ConfGraph BuildConfGraph(CFGType &cfg) {
|
||||||
|
std::unordered_map<ConfGraphNode *, std::unordered_set<ConfGraphNode *>> edges;
|
||||||
|
ConfGraph res;
|
||||||
|
for (size_t id = 0; id < cfg.id_to_var.size(); id++) {
|
||||||
|
auto node = std::make_shared<ConfGraphNode>();
|
||||||
|
node->var_ids.push_back(id);
|
||||||
|
res.id_to_node[id] = node.get();
|
||||||
|
res.nodes.push_back(node);
|
||||||
|
node->is_binded_with_physical_reg = false;
|
||||||
|
}
|
||||||
|
for (auto cfg_node : cfg.nodes) {
|
||||||
|
for (const auto &[act, out_active] : cfg_node->action_out_active_vars) {
|
||||||
|
const auto &def_vars = cfg_node->action_def_vars[act];
|
||||||
|
for (auto def_var : def_vars) {
|
||||||
|
for (auto out_var : out_active) {
|
||||||
|
edges[res.id_to_node[def_var]].insert(res.id_to_node[out_var]);
|
||||||
|
edges[res.id_to_node[out_var]].insert(res.id_to_node[def_var]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &[u, neighbors] : edges) {
|
||||||
|
for (auto v : neighbors) {
|
||||||
|
u->neighbors.push_back(v);
|
||||||
|
res.adj_table[u][v] = std::prev(u->neighbors.end());
|
||||||
|
}
|
||||||
|
u->neighbors.sort();
|
||||||
|
}
|
||||||
|
for (auto node : res.nodes) {
|
||||||
|
node->degree = node->neighbors.size();
|
||||||
|
}
|
||||||
|
for (auto reg : allocating_regs) {
|
||||||
|
size_t reg_id = cfg.var_to_id["%reg." + reg];
|
||||||
|
res.id_to_node[reg_id]->is_binded_with_physical_reg = true;
|
||||||
|
res.id_to_node[reg_id]->color = std::stoi(reg.substr(1));
|
||||||
|
res.id_to_node[reg_id]->degree = ConfGraphNode::kInf;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
const static size_t kMaxRegs = allocating_regs.size();
|
||||||
|
void InitializeBeforeColoring(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confgraph) {
|
||||||
|
confgraph.stack.clear();
|
||||||
|
confgraph.actual_spills.clear();
|
||||||
|
|
||||||
ConfGraph BuildConfGraph(CFGType &cfg) { ; }
|
confgraph.low_degree_and_not_move_related.clear();
|
||||||
bool TryColoring(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph& confgraph) { return false; }
|
confgraph.low_degree_and_move_related.clear();
|
||||||
|
confgraph.high_degree_nodes.clear(); // note that physical registers are not included in this set
|
||||||
|
|
||||||
|
confgraph.pending_moves.clear();
|
||||||
|
confgraph.potential_moves.clear();
|
||||||
|
}
|
||||||
|
bool ConductColoring(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confgraph) {
|
||||||
|
InitializeBeforeColoring(src, cfg, confgraph);
|
||||||
|
do {
|
||||||
|
if (confgraph.low_degree_and_not_move_related.size() > 0) {
|
||||||
|
// simplify
|
||||||
|
} else if (confgraph.pending_moves.size() > 0) {
|
||||||
|
// coalesce
|
||||||
|
} else if (confgraph.low_degree_and_move_related.size() > 0) {
|
||||||
|
// freeze
|
||||||
|
} else if (confgraph.high_degree_nodes.size() > 0) {
|
||||||
|
// potential spill
|
||||||
|
}
|
||||||
|
} while (confgraph.low_degree_and_not_move_related.size() > 0 || confgraph.pending_moves.size() > 0 ||
|
||||||
|
confgraph.low_degree_and_move_related.size() > 0 || confgraph.high_degree_nodes.size() > 0);
|
||||||
|
// select and spill
|
||||||
|
if (confgraph.actual_spills.size() > 0) {
|
||||||
|
std::cerr << "spilled " << confgraph.actual_spills.size() << " nodes" << std::endl;
|
||||||
|
// allocate memory for spilled nodes
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
@ -6,14 +6,6 @@
|
|||||||
#include "phieliminate.h"
|
#include "phieliminate.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
// RISC-V calling convention compatible
|
|
||||||
static std::vector<std::string> held_tmp_regs = {"x28", "x29", "x30", "x31"};
|
|
||||||
static std::vector<std::string> callee_saved_regs = {"x3", "x4", "x9", "x18", "x19", "x20", "x21",
|
|
||||||
"x22", "x23", "x24", "x25", "x26", "x27"};
|
|
||||||
static std::vector<std::string> caller_saved_regs = {"x5", "x6", "x7", "x10", "x11", "x12",
|
|
||||||
"x13", "x14", "x15", "x16", "x17"};
|
|
||||||
static std::vector<std::string> arg_regs = {"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"};
|
|
||||||
static std::string zero = "x0", sp = "x2", ra = "x1", fp = "x8";
|
|
||||||
void EnforcePhysicalRegs(CFGType &cfg) {
|
void EnforcePhysicalRegs(CFGType &cfg) {
|
||||||
using namespace opt;
|
using namespace opt;
|
||||||
// process callee side
|
// process callee side
|
||||||
@ -128,14 +120,16 @@ void EnforcePhysicalRegs(CFGType &cfg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ConductRegAllocForFunction(std::shared_ptr<FunctionDefItem> func) {
|
void ConductRegAllocForFunction(std::shared_ptr<FunctionDefItem> func) {
|
||||||
|
std::cerr << "processing function " << func->func_name_raw << std::endl;
|
||||||
CFGType cfg;
|
CFGType cfg;
|
||||||
ConfGraph confgraph;
|
ConfGraph confgraph;
|
||||||
|
cfg = BuildCFGForFunction(func);
|
||||||
|
EnforcePhysicalRegs(cfg);
|
||||||
do {
|
do {
|
||||||
cfg = BuildCFGForFunction(func);
|
cfg = BuildCFGForFunction(func);
|
||||||
EnforcePhysicalRegs(cfg);
|
|
||||||
LiveAnalysis(cfg);
|
LiveAnalysis(cfg);
|
||||||
confgraph = BuildConfGraph(cfg);
|
confgraph = BuildConfGraph(cfg);
|
||||||
} while (TryColoring(func, cfg, confgraph));
|
} while (ConductColoring(func, cfg, confgraph));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModuleItem> RegAlloc(std::shared_ptr<ModuleItem> src) {
|
std::shared_ptr<ModuleItem> RegAlloc(std::shared_ptr<ModuleItem> src) {
|
||||||
|
Reference in New Issue
Block a user