half way of coloring
This commit is contained in:
@ -14,6 +14,8 @@ ConfGraph BuildConfGraph(CFGType &cfg) {
|
||||
res.id_to_node[id] = node.get();
|
||||
res.nodes.push_back(node);
|
||||
node->is_binded_with_physical_reg = false;
|
||||
node->is_merged_into = node.get(); // the same as `fa` in DSU
|
||||
node->is_temporarily_removed = false;
|
||||
}
|
||||
for (auto cfg_node : cfg.nodes) {
|
||||
for (const auto &[act, out_active] : cfg_node->action_out_active_vars) {
|
||||
@ -42,10 +44,22 @@ ConfGraph BuildConfGraph(CFGType &cfg) {
|
||||
res.id_to_node[reg_id]->color = std::stoi(reg.substr(1));
|
||||
res.id_to_node[reg_id]->degree = ConfGraphNode::kInf;
|
||||
}
|
||||
for (auto cfg_node : cfg.nodes) {
|
||||
auto block = cfg_node->corresponding_block;
|
||||
for (auto act : block->actions) {
|
||||
if (auto move_act = std::dynamic_pointer_cast<opt::MoveInstruct>(act)) {
|
||||
size_t src_id = cfg.var_to_id[move_act->src_full];
|
||||
size_t dest_id = cfg.var_to_id[move_act->dest_full];
|
||||
res.id_to_node[src_id]->move_neighbors.push_back({res.id_to_node[dest_id], move_act.get()});
|
||||
res.id_to_node[dest_id]->move_neighbors.push_back({res.id_to_node[src_id], move_act.get()});
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
const static size_t kMaxRegs = allocating_regs.size();
|
||||
void InitializeBeforeColoring(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confgraph) {
|
||||
void InitializeBeforeColoring([[maybe_unused]] std::shared_ptr<FunctionDefItem> src, [[maybe_unused]] CFGType &cfg,
|
||||
ConfGraph &confgraph) {
|
||||
confgraph.stack.clear();
|
||||
confgraph.actual_spills.clear();
|
||||
|
||||
@ -55,18 +69,137 @@ void InitializeBeforeColoring(std::shared_ptr<FunctionDefItem> src, CFGType &cfg
|
||||
|
||||
confgraph.pending_moves.clear();
|
||||
confgraph.potential_moves.clear();
|
||||
for (auto confg_node : confgraph.nodes) {
|
||||
for (auto [move_neighbor, move] : confg_node->move_neighbors) {
|
||||
if (confgraph.adj_table[confg_node.get()].find(move_neighbor) == confgraph.adj_table[confg_node.get()].end()) {
|
||||
if (confg_node->degree < kMaxRegs && move_neighbor->degree < kMaxRegs) {
|
||||
confgraph.pending_moves.insert(move);
|
||||
} else if (confg_node->is_binded_with_physical_reg || move_neighbor->is_binded_with_physical_reg) {
|
||||
if (confg_node->is_binded_with_physical_reg && move_neighbor->is_binded_with_physical_reg)
|
||||
throw std::runtime_error(
|
||||
"something strange happened: at the beginning two physical registers are directly move related");
|
||||
confgraph.pending_moves.insert(move);
|
||||
} else {
|
||||
confgraph.potential_moves.insert(move);
|
||||
}
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
if (confg_node->degree < kMaxRegs) {
|
||||
if (confg_node->move_neighbors.size() == 0) {
|
||||
confgraph.low_degree_and_not_move_related.insert(confg_node.get());
|
||||
} else {
|
||||
confgraph.low_degree_and_move_related.insert(confg_node.get());
|
||||
}
|
||||
} else if (!confg_node->is_binded_with_physical_reg) {
|
||||
confgraph.high_degree_nodes.insert(confg_node.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DetachNode(ConfGraphNode *node, ConfGraph &confgraph, bool during_selecting = false) {
|
||||
// this function operates on the conflict graph, temporarily remove the node from the graph, it do nothing on the move
|
||||
// link graph although they share the same node set
|
||||
// It is also responsible for maintaining all the changes caused by the removal of the node
|
||||
}
|
||||
|
||||
void JoinNode(ConfGraphNode *node, ConfGraph &confgraph, bool during_selecting = false) {
|
||||
// this function operates on the conflict graph, temporarily remove the node from the graph, it do nothing on the move
|
||||
// link graph although they share the same node set
|
||||
// It is also responsible for maintaining all the changes caused by the removal of the node
|
||||
}
|
||||
|
||||
void MergeNodeInto(ConfGraphNode *node, ConfGraphNode *target, ConfGraph &confgraph) {
|
||||
// this function operates on both the conflict graph and the move link graph, and the effect is permanent
|
||||
// It is also responsible for maintaining all the changes caused by the merge of the node
|
||||
}
|
||||
|
||||
void Simplify(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confgraph) {
|
||||
auto u = *(confgraph.low_degree_and_not_move_related.begin());
|
||||
confgraph.low_degree_and_not_move_related.erase(u);
|
||||
DetachNode(u, confgraph);
|
||||
confgraph.stack.push_back(u);
|
||||
}
|
||||
|
||||
void Coalesce(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confgraph) {
|
||||
auto move = *(confgraph.pending_moves.begin());
|
||||
confgraph.pending_moves.erase(move);
|
||||
size_t src_id = cfg.var_to_id[move->src_full];
|
||||
size_t dest_id = cfg.var_to_id[move->dest_full];
|
||||
auto src_node = confgraph.id_to_node[src_id];
|
||||
auto dest_node = confgraph.id_to_node[dest_id];
|
||||
if (confgraph.adj_table[src_node].find(dest_node) != confgraph.adj_table[src_node].end()) {
|
||||
// no need to update low_degree_and_move_related, when confgraph.pending_moves.size()==0, nodes in
|
||||
// low_degree_and_move_related will automatically be moved to low_degree_and_not_move_related
|
||||
return;
|
||||
}
|
||||
if (src_node->is_binded_with_physical_reg && dest_node->is_binded_with_physical_reg)
|
||||
throw std::runtime_error("something strange happened: two physical registers do not conflict");
|
||||
if (src_node->is_binded_with_physical_reg || dest_node->is_binded_with_physical_reg) {
|
||||
// George condition
|
||||
if (src_node->is_binded_with_physical_reg) {
|
||||
std::swap(src_node, dest_node);
|
||||
}
|
||||
bool condition_satisfied = true;
|
||||
for (auto t : src_node->neighbors) {
|
||||
if (t->degree >= kMaxRegs && confgraph.adj_table[t].find(dest_node) == confgraph.adj_table[t].end()) {
|
||||
condition_satisfied = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (condition_satisfied) {
|
||||
MergeNodeInto(src_node, dest_node, confgraph);
|
||||
} else {
|
||||
confgraph.pending_moves.insert(move);
|
||||
}
|
||||
} else {
|
||||
// Briggs condition
|
||||
std::unordered_set<ConfGraphNode *> dangerous_neighbors;
|
||||
for (auto t : src_node->neighbors) {
|
||||
if (t != dest_node && t->degree >= kMaxRegs) {
|
||||
dangerous_neighbors.insert(t);
|
||||
}
|
||||
}
|
||||
for (auto t : dest_node->neighbors) {
|
||||
if (t != src_node && t->degree >= kMaxRegs) {
|
||||
dangerous_neighbors.insert(t);
|
||||
}
|
||||
}
|
||||
if (dangerous_neighbors.size() < kMaxRegs) {
|
||||
MergeNodeInto(src_node, dest_node, confgraph);
|
||||
} else {
|
||||
confgraph.pending_moves.insert(move);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Freeze(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confgraph) {
|
||||
auto u = *confgraph.low_degree_and_move_related.begin();
|
||||
confgraph.low_degree_and_move_related.erase(u);
|
||||
confgraph.low_degree_and_not_move_related.insert(u);
|
||||
for (auto [_, ins] : u->move_neighbors) {
|
||||
confgraph.potential_moves.erase(ins);
|
||||
}
|
||||
}
|
||||
|
||||
void PotentailSpill(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confgraph) {
|
||||
auto u = *confgraph.high_degree_nodes.begin();
|
||||
confgraph.high_degree_nodes.erase(u);
|
||||
DetachNode(u, confgraph);
|
||||
confgraph.stack.push_back(u);
|
||||
}
|
||||
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
|
||||
Simplify(src, cfg, confgraph);
|
||||
} else if (confgraph.pending_moves.size() > 0) {
|
||||
// coalesce
|
||||
Coalesce(src, cfg, confgraph);
|
||||
} else if (confgraph.low_degree_and_move_related.size() > 0) {
|
||||
// freeze
|
||||
Freeze(src, cfg, confgraph);
|
||||
} else if (confgraph.high_degree_nodes.size() > 0) {
|
||||
// potential spill
|
||||
PotentailSpill(src, cfg, confgraph);
|
||||
}
|
||||
} 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);
|
||||
@ -74,6 +207,7 @@ bool ConductColoring(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGra
|
||||
if (confgraph.actual_spills.size() > 0) {
|
||||
std::cerr << "spilled " << confgraph.actual_spills.size() << " nodes" << std::endl;
|
||||
// allocate memory for spilled nodes
|
||||
// rewrite the spilled nodes
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
Reference in New Issue
Block a user