basically can color
This commit is contained in:
@ -30,6 +30,7 @@ ConfGraph BuildConfGraph(CFGType &cfg) {
|
||||
}
|
||||
for (const auto &[u, neighbors] : edges) {
|
||||
for (auto v : neighbors) {
|
||||
if (u == v) continue;
|
||||
u->neighbors.push_back(v);
|
||||
res.adj_table[u][v] = std::prev(u->neighbors.end());
|
||||
}
|
||||
@ -42,16 +43,26 @@ ConfGraph BuildConfGraph(CFGType &cfg) {
|
||||
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));
|
||||
std::cerr << "coloring node whith id=" << reg_id << " with color=" << res.id_to_node[reg_id]->color << std::endl;
|
||||
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)) {
|
||||
if (!VRegCheck(move_act->src_full)) continue;
|
||||
if (cfg.var_to_id.find(move_act->src_full) == cfg.var_to_id.end()) {
|
||||
move_act->RecursivePrint(std::cerr);
|
||||
std::cerr << std::endl;
|
||||
throw std::runtime_error("move_act->src_full not found in var_to_id");
|
||||
}
|
||||
if (cfg.var_to_id.find(move_act->dest_full) == cfg.var_to_id.end()) {
|
||||
throw std::runtime_error("move_act->dest_full not found in var_to_id");
|
||||
}
|
||||
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()});
|
||||
res.id_to_node[src_id]->original_move_neighbors.push_back({res.id_to_node[dest_id], move_act.get()});
|
||||
res.id_to_node[dest_id]->original_move_neighbors.push_back({res.id_to_node[src_id], move_act.get()});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,14 +81,19 @@ void InitializeBeforeColoring([[maybe_unused]] std::shared_ptr<FunctionDefItem>
|
||||
confgraph.pending_moves.clear();
|
||||
confgraph.potential_moves.clear();
|
||||
for (auto confg_node : confgraph.nodes) {
|
||||
for (auto [move_neighbor, move] : confg_node->move_neighbors) {
|
||||
for (auto [move_neighbor, move] : confg_node->original_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)
|
||||
if (confg_node->is_binded_with_physical_reg && move_neighbor->is_binded_with_physical_reg) {
|
||||
std::cerr << confg_node->var_ids.front() << " " << move_neighbor->var_ids.front() << std::endl;
|
||||
std::cerr << confg_node->color << " " << move_neighbor->color << std::endl;
|
||||
move->RecursivePrint(std::cerr);
|
||||
std::cerr << std::endl;
|
||||
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);
|
||||
@ -87,7 +103,7 @@ void InitializeBeforeColoring([[maybe_unused]] std::shared_ptr<FunctionDefItem>
|
||||
}
|
||||
}
|
||||
if (confg_node->degree < kMaxRegs) {
|
||||
if (confg_node->move_neighbors.size() == 0) {
|
||||
if (confg_node->original_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());
|
||||
@ -98,13 +114,59 @@ void InitializeBeforeColoring([[maybe_unused]] std::shared_ptr<FunctionDefItem>
|
||||
}
|
||||
}
|
||||
|
||||
void DetachNode(ConfGraphNode *node, ConfGraph &confgraph, bool during_selecting = false) {
|
||||
void DetachNode(ConfGraphNode *node, ConfGraph &confgraph) {
|
||||
// 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
|
||||
if (node->is_temporarily_removed)
|
||||
throw std::runtime_error("something strange happened: a temporarily removed node is removed");
|
||||
node->is_temporarily_removed = true;
|
||||
if (node->is_binded_with_physical_reg)
|
||||
throw std::runtime_error("something strange happened: a physical register is removed");
|
||||
std::cerr << "detaching node containing var ids:";
|
||||
for (auto id : node->var_ids) {
|
||||
std::cerr << id << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
for (auto neighbor : node->neighbors_half_available) {
|
||||
neighbor->neighbors_half_available.erase(confgraph.adj_table_half_available[neighbor][node]);
|
||||
confgraph.adj_table_half_available[neighbor].erase(node);
|
||||
// node->neighbors_half_available.erase(confgraph.adj_table_half_available[node][neighbor]);
|
||||
confgraph.adj_table_half_available[node].erase(neighbor);
|
||||
neighbor->neighbors_not_available.push_back(node);
|
||||
confgraph.adj_table_not_available[neighbor][node] = std::prev(neighbor->neighbors_not_available.end());
|
||||
node->neighbors_not_available.push_back(neighbor);
|
||||
confgraph.adj_table_not_available[node][neighbor] = std::prev(node->neighbors_not_available.end());
|
||||
}
|
||||
node->neighbors_half_available.clear();
|
||||
for (auto neighbor : node->neighbors) {
|
||||
if (neighbor == node) throw std::runtime_error("something strange happened: a node is its own neighbor");
|
||||
neighbor->neighbors.erase(confgraph.adj_table[neighbor][node]);
|
||||
confgraph.adj_table[neighbor].erase(node);
|
||||
neighbor->degree = neighbor->neighbors.size();
|
||||
|
||||
confgraph.low_degree_and_not_move_related.erase(neighbor);
|
||||
confgraph.low_degree_and_move_related.erase(neighbor);
|
||||
confgraph.high_degree_nodes.erase(neighbor);
|
||||
if (!neighbor->is_binded_with_physical_reg) {
|
||||
if (neighbor->degree >= kMaxRegs) {
|
||||
confgraph.high_degree_nodes.insert(neighbor);
|
||||
} else {
|
||||
confgraph.low_degree_and_move_related.insert(neighbor); // it may be wrong, but it is safe
|
||||
}
|
||||
}
|
||||
|
||||
// node->neighbors.erase(confgraph.adj_table[node][neighbor]);
|
||||
confgraph.adj_table[node].erase(neighbor);
|
||||
neighbor->neighbors_half_available.push_back(node);
|
||||
confgraph.adj_table_half_available[neighbor][node] = std::prev(neighbor->neighbors_half_available.end());
|
||||
node->neighbors_half_available.push_back(neighbor);
|
||||
confgraph.adj_table_half_available[node][neighbor] = std::prev(node->neighbors_half_available.end());
|
||||
}
|
||||
node->neighbors.clear();
|
||||
}
|
||||
|
||||
void JoinNode(ConfGraphNode *node, ConfGraph &confgraph, bool during_selecting = false) {
|
||||
void JoinNode(ConfGraphNode *node, ConfGraph &confgraph) {
|
||||
// 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
|
||||
@ -113,6 +175,74 @@ void JoinNode(ConfGraphNode *node, ConfGraph &confgraph, bool during_selecting =
|
||||
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
|
||||
if (node->is_temporarily_removed)
|
||||
throw std::runtime_error("something strange happened: a temporarily removed node is merged");
|
||||
std::cerr << "node ids:";
|
||||
for (auto id : node->var_ids) {
|
||||
std::cerr << id << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "target ids:";
|
||||
for (auto id : target->var_ids) {
|
||||
std::cerr << id << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
confgraph.low_degree_and_move_related.erase(node);
|
||||
confgraph.low_degree_and_not_move_related.erase(node);
|
||||
confgraph.high_degree_nodes.erase(node);
|
||||
node->is_merged_into = target;
|
||||
target->var_ids.splice(target->var_ids.end(), node->var_ids);
|
||||
for (auto neighbor : node->neighbors) {
|
||||
if (neighbor == target) continue;
|
||||
if (confgraph.adj_table[target].find(neighbor) == confgraph.adj_table[target].end()) {
|
||||
target->neighbors.push_back(neighbor);
|
||||
confgraph.adj_table[target][neighbor] = std::prev(target->neighbors.end());
|
||||
neighbor->neighbors.push_back(target);
|
||||
confgraph.adj_table[neighbor][target] = std::prev(neighbor->neighbors.end());
|
||||
}
|
||||
neighbor->neighbors.erase(confgraph.adj_table[neighbor][node]);
|
||||
// node->neighbors.erase(confgraph.adj_table[node][neighbor]);
|
||||
confgraph.adj_table[neighbor].erase(node);
|
||||
confgraph.adj_table[node].erase(neighbor);
|
||||
neighbor->degree = neighbor->neighbors.size();
|
||||
confgraph.low_degree_and_not_move_related.erase(neighbor);
|
||||
confgraph.low_degree_and_move_related.erase(neighbor);
|
||||
confgraph.high_degree_nodes.erase(neighbor);
|
||||
if (!neighbor->is_binded_with_physical_reg) {
|
||||
if (neighbor->degree >= kMaxRegs) {
|
||||
confgraph.high_degree_nodes.insert(neighbor);
|
||||
} else {
|
||||
confgraph.low_degree_and_move_related.insert(neighbor); // it may be wrong, but it is safe
|
||||
}
|
||||
}
|
||||
}
|
||||
node->neighbors.clear();
|
||||
for (auto neighbor : node->neighbors_half_available) {
|
||||
if (neighbor == target) continue;
|
||||
if (confgraph.adj_table_half_available[target].find(neighbor) == confgraph.adj_table_half_available[target].end()) {
|
||||
target->neighbors_half_available.push_back(neighbor);
|
||||
confgraph.adj_table_half_available[target][neighbor] = std::prev(target->neighbors_half_available.end());
|
||||
neighbor->neighbors_half_available.push_back(target);
|
||||
confgraph.adj_table_half_available[neighbor][target] = std::prev(neighbor->neighbors_half_available.end());
|
||||
}
|
||||
neighbor->neighbors_half_available.erase(confgraph.adj_table_half_available[neighbor][node]);
|
||||
// node->neighbors_half_available.erase(confgraph.adj_table_half_available[node][neighbor]);
|
||||
confgraph.adj_table_half_available[neighbor].erase(node);
|
||||
confgraph.adj_table_half_available[node].erase(neighbor);
|
||||
}
|
||||
node->neighbors_half_available.clear();
|
||||
if (node->neighbors_not_available.size() > 0) {
|
||||
throw std::runtime_error(
|
||||
"something strange happened: neighbors_not_available is not empty in function MergeNodeInto");
|
||||
}
|
||||
target->degree = target->neighbors.size();
|
||||
if (!target->is_binded_with_physical_reg) {
|
||||
if (target->degree >= kMaxRegs) {
|
||||
confgraph.high_degree_nodes.insert(target);
|
||||
} else {
|
||||
confgraph.low_degree_and_move_related.insert(target); // it may be wrong, but it is safe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Simplify(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confgraph) {
|
||||
@ -128,7 +258,12 @@ void Coalesce(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &con
|
||||
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];
|
||||
src_node = ConfGraphNode::FindFather(src_node);
|
||||
auto dest_node = confgraph.id_to_node[dest_id];
|
||||
dest_node = ConfGraphNode::FindFather(dest_node);
|
||||
if (src_node == dest_node) {
|
||||
return;
|
||||
}
|
||||
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
|
||||
@ -151,7 +286,7 @@ void Coalesce(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &con
|
||||
if (condition_satisfied) {
|
||||
MergeNodeInto(src_node, dest_node, confgraph);
|
||||
} else {
|
||||
confgraph.pending_moves.insert(move);
|
||||
confgraph.potential_moves.insert(move);
|
||||
}
|
||||
} else {
|
||||
// Briggs condition
|
||||
@ -169,7 +304,7 @@ void Coalesce(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &con
|
||||
if (dangerous_neighbors.size() < kMaxRegs) {
|
||||
MergeNodeInto(src_node, dest_node, confgraph);
|
||||
} else {
|
||||
confgraph.pending_moves.insert(move);
|
||||
confgraph.potential_moves.insert(move);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,7 +313,7 @@ void Freeze(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confg
|
||||
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) {
|
||||
for (auto [_, ins] : u->original_move_neighbors) {
|
||||
confgraph.potential_moves.erase(ins);
|
||||
}
|
||||
}
|
||||
@ -190,8 +325,52 @@ void PotentailSpill(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGrap
|
||||
confgraph.stack.push_back(u);
|
||||
}
|
||||
bool ConductColoring(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGraph &confgraph) {
|
||||
if (cfg.id_to_var.size() != cfg.var_to_id.size()) {
|
||||
throw std::runtime_error("something strange happened: id_to_var and var_to_id do not match");
|
||||
}
|
||||
for (size_t i = 0; i < cfg.id_to_var.size(); i++) {
|
||||
std::cerr << "id=" << i << " var=" << cfg.id_to_var[i] << std::endl;
|
||||
if (i != cfg.var_to_id[cfg.id_to_var[i]]) {
|
||||
throw std::runtime_error("something strange happened: id_to_var and var_to_id do not match");
|
||||
}
|
||||
}
|
||||
if (cfg.id_to_var.size() != confgraph.nodes.size()) {
|
||||
throw std::runtime_error("something strange happened: id_to_var and confgraph.nodes do not match");
|
||||
}
|
||||
if (cfg.id_to_var.size() != confgraph.id_to_node.size()) {
|
||||
throw std::runtime_error("something strange happened: id_to_var and confgraph.nodes do not match");
|
||||
}
|
||||
for (size_t i = 0; i < cfg.id_to_var.size(); i++) {
|
||||
if (confgraph.id_to_node[i]->var_ids.size() != 1)
|
||||
throw std::runtime_error("something strange happened: id_to_node.size()!=1");
|
||||
if (confgraph.id_to_node[i]->var_ids.front() != i)
|
||||
throw std::runtime_error("something strange happened: id_to_node[0]!=i");
|
||||
}
|
||||
InitializeBeforeColoring(src, cfg, confgraph);
|
||||
do {
|
||||
// std::cerr << std::endl;
|
||||
// std::cerr << "confgraph.low_degree_and_not_move_related.size()=" <<
|
||||
// confgraph.low_degree_and_not_move_related.size()
|
||||
// << std::endl;
|
||||
// std::cerr << "confgraph.pending_moves.size()=" << confgraph.pending_moves.size() << std::endl;
|
||||
// std::cerr << "confgraph.low_degree_and_move_related.size()=" << confgraph.low_degree_and_move_related.size()
|
||||
// << std::endl;
|
||||
// std::cerr << "confgraph.high_degree_nodes.size()=" << confgraph.high_degree_nodes.size() << std::endl;
|
||||
for (auto node : confgraph.low_degree_and_not_move_related) {
|
||||
if (node->is_binded_with_physical_reg) {
|
||||
throw std::runtime_error("something strange happened: node is binded with physical reg");
|
||||
}
|
||||
}
|
||||
for (auto node : confgraph.low_degree_and_move_related) {
|
||||
if (node->is_binded_with_physical_reg) {
|
||||
throw std::runtime_error("something strange happened: node is binded with physical reg");
|
||||
}
|
||||
}
|
||||
for (auto node : confgraph.high_degree_nodes) {
|
||||
if (node->is_binded_with_physical_reg) {
|
||||
throw std::runtime_error("something strange happened: node is binded with physical reg");
|
||||
}
|
||||
}
|
||||
if (confgraph.low_degree_and_not_move_related.size() > 0) {
|
||||
Simplify(src, cfg, confgraph);
|
||||
} else if (confgraph.pending_moves.size() > 0) {
|
||||
@ -204,6 +383,7 @@ bool ConductColoring(std::shared_ptr<FunctionDefItem> src, CFGType &cfg, ConfGra
|
||||
} 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
|
||||
return false;
|
||||
if (confgraph.actual_spills.size() > 0) {
|
||||
std::cerr << "spilled " << confgraph.actual_spills.size() << " nodes" << std::endl;
|
||||
// allocate memory for spilled nodes
|
||||
|
Reference in New Issue
Block a user