half way of coloring

This commit is contained in:
2024-10-21 10:15:45 +00:00
parent 11b9f31b7a
commit 04ab579484
2 changed files with 152 additions and 7 deletions

View File

@ -1,4 +1,5 @@
#pragma once
#include <cstddef>
#include "IR/IR_basic.h"
#include "cfg.h"
class ConfGraphNode {
@ -9,8 +10,17 @@ class ConfGraphNode {
size_t degree;
bool is_binded_with_physical_reg;
std::list<ConfGraphNode *> neighbors;
std::list<opt::MoveInstruct *> move_neighbors;
ConfGraphNode() = default;
std::list<std::pair<ConfGraphNode *, opt::MoveInstruct *>> move_neighbors;
// the following are for graph maintenance
ConfGraphNode *is_merged_into;
static ConfGraphNode *FindFather(ConfGraphNode *x) {
if (x->is_merged_into == x) return x;
return x->is_merged_into = FindFather(x->is_merged_into);
}
bool is_temporarily_removed;
std::list<ConfGraphNode *> neighbors_half_available;
std::list<ConfGraphNode *> neighbors_not_available;
};
class ConfGraph {
public:
@ -27,6 +37,7 @@ class ConfGraph {
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;
};

View File

@ -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;