basically can color

This commit is contained in:
2024-10-21 16:42:40 +00:00
parent 04ab579484
commit 8216cb774c
8 changed files with 284 additions and 51 deletions

View File

@ -38,6 +38,15 @@ class CFGType {
std::vector<std::string> id_to_var;
std::unordered_map<std::string, size_t> var_to_id;
FunctionDefItem *corresponding_func;
void init() {
nodes.clear();
entry = nullptr;
block_to_node.clear();
label_to_block.clear();
id_to_var.clear();
var_to_id.clear();
corresponding_func = nullptr;
}
};
namespace opt {
@ -48,7 +57,7 @@ class MoveInstruct : public ActionItem {
LLVMType ty;
MoveInstruct() = default;
void RecursivePrint([[maybe_unused]] std::ostream &os) const {
throw std::runtime_error("Move instruction is not an actual LLVM IR instruction");
os << "[Persudo] " << dest_full << " <-- " << src_full << "\n";
}
};
} // namespace opt
@ -161,4 +170,9 @@ const static std::vector<std::string> caller_saved_regs = {"x5", "x6", "x7",
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"};
"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"};
inline bool VRegCheck(const std::string &s) {
if (s[0] != '%') return false;
return true;
}

View File

@ -5,12 +5,11 @@
class ConfGraphNode {
public:
const static size_t kInf = (std::numeric_limits<size_t>::max()) >> 2;
std::vector<size_t> var_ids;
std::list<size_t> var_ids;
size_t color;
size_t degree;
bool is_binded_with_physical_reg;
std::list<ConfGraphNode *> neighbors;
std::list<std::pair<ConfGraphNode *, opt::MoveInstruct *>> move_neighbors;
// the following are for graph maintenance
ConfGraphNode *is_merged_into;
@ -21,6 +20,7 @@ class ConfGraphNode {
bool is_temporarily_removed;
std::list<ConfGraphNode *> neighbors_half_available;
std::list<ConfGraphNode *> neighbors_not_available;
std::list<std::pair<ConfGraphNode *, opt::MoveInstruct *>> original_move_neighbors;
};
class ConfGraph {
public:
@ -39,6 +39,24 @@ class ConfGraph {
std::unordered_set<opt::MoveInstruct *> pending_moves;
std::unordered_set<opt::MoveInstruct *> potential_moves;
std::unordered_map<ConfGraphNode *, std::unordered_map<ConfGraphNode *, std::list<ConfGraphNode *>::iterator>>
adj_table_half_available;
std::unordered_map<ConfGraphNode *, std::unordered_map<ConfGraphNode *, std::list<ConfGraphNode *>::iterator>>
adj_table_not_available;
void init() {
id_to_node.clear();
nodes.clear();
adj_table.clear();
stack.clear();
actual_spills.clear();
low_degree_and_not_move_related.clear();
low_degree_and_move_related.clear();
high_degree_nodes.clear();
pending_moves.clear();
potential_moves.clear();
adj_table_half_available.clear();
adj_table_not_available.clear();
}
};
ConfGraph BuildConfGraph(CFGType &cfg);

View File

@ -11,17 +11,13 @@ class ForceDef : public ActionItem {
std::string var_full;
LLVMType ty;
ForceDef() = default;
void RecursivePrint(std::ostream &os) const {
throw std::runtime_error("ForceDef instruction is not an actual LLVM IR instruction");
}
void RecursivePrint(std::ostream &os) const { os << "[Persudo] def " << var_full << "\n"; }
};
class ForceUse : public ActionItem {
public:
std::string var_full;
ForceUse() = default;
void RecursivePrint(std::ostream &os) const {
throw std::runtime_error("ForceUse instruction is not an actual LLVM IR instruction");
}
void RecursivePrint(std::ostream &os) const { os << "[Persudo] use " << var_full << "\n"; }
};
class LoadSpilledArgs : public ActionItem {
public:
@ -30,7 +26,7 @@ class LoadSpilledArgs : public ActionItem {
LLVMType ty;
LoadSpilledArgs() = default;
void RecursivePrint(std::ostream &os) const {
throw std::runtime_error("LoadSpilledArgs instruction is not an actual LLVM IR instruction");
os << "[Persudo] load spilled args " << var_full << "with id=" << arg_id << "\n";
}
};
@ -41,7 +37,7 @@ class StoreSpilledArgs : public ActionItem {
LLVMType ty;
StoreSpilledArgs() = default;
void RecursivePrint(std::ostream &os) const {
throw std::runtime_error("StoreSpilledArgs instruction is not an actual LLVM IR instruction");
os << "[Persudo] store spilled args " << var_full << "with id=" << arg_id << "\n";
}
};
} // namespace opt

View File

@ -48,6 +48,7 @@ int main(int argc, char **argv) {
auto IR_with_out_allocas = Mem2Reg(IR);
IR_with_out_allocas->RecursivePrint(fout);
auto IR_with_out_phis = PhiEliminate(IR_with_out_allocas);
// IR_with_out_phis->RecursivePrint(fout);
auto alloced_code = RegAlloc(IR_with_out_phis);
}
} catch (const SemanticError &err) {

View File

@ -3,23 +3,20 @@
CFGType BuildCFGForFunction(const std::shared_ptr<FunctionDefItem> &func) {
CFGType res;
auto init_block = func->init_block;
if (!func->init_block) {
// throw std::runtime_error("Function does not have an init block");
if (func->basic_blocks.size() == 0) throw std::runtime_error("Function does not have any block");
init_block = func->basic_blocks[0];
if (func->init_block) {
res.label_to_block[func->init_block->label_full] = func->init_block.get();
res.nodes.push_back(std::make_shared<CFGNodeType>());
res.entry = res.nodes.back().get();
res.entry->corresponding_block = func->init_block.get();
res.block_to_node[func->init_block.get()] = res.entry;
}
res.label_to_block[init_block->label_full] = init_block.get();
res.nodes.push_back(std::make_shared<CFGNodeType>());
res.entry = res.nodes.back().get();
res.entry->corresponding_block = init_block.get();
res.block_to_node[init_block.get()] = res.entry;
for (auto block_ptr : func->basic_blocks) {
res.label_to_block[block_ptr->label_full] = block_ptr.get();
res.nodes.push_back(std::make_shared<CFGNodeType>());
res.nodes.back()->corresponding_block = block_ptr.get();
res.block_to_node[block_ptr.get()] = res.nodes.back().get();
}
res.entry = res.nodes.front().get();
// now add information for successors and predecessors
for (auto node : res.nodes) {
auto block = node->corresponding_block;

View File

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

View File

@ -7,41 +7,46 @@
using namespace opt;
void VarCollect(CFGType &cfg, std::vector<std::string> &id_to_var, std::unordered_map<std::string, size_t> &var_to_id) {
auto TryAddVar = [&](const std::string &var) {
if (var_to_id.find(var) == var_to_id.end()) {
id_to_var.push_back(var);
var_to_id[var] = id_to_var.size() - 1;
}
};
for (auto node : cfg.nodes) {
auto block = node->corresponding_block;
for (auto act : block->actions) {
if (auto bin_act = std::dynamic_pointer_cast<BinaryOperationAction>(act)) {
id_to_var.push_back(bin_act->result_full);
var_to_id[bin_act->result_full] = id_to_var.size() - 1;
TryAddVar(bin_act->result_full);
} else if (auto load_act = std::dynamic_pointer_cast<LoadAction>(act)) {
id_to_var.push_back(load_act->result_full);
var_to_id[load_act->result_full] = id_to_var.size() - 1;
TryAddVar(load_act->result_full);
} else if (auto get_act = std::dynamic_pointer_cast<GetElementPtrAction>(act)) {
id_to_var.push_back(get_act->result_full);
var_to_id[get_act->result_full] = id_to_var.size() - 1;
TryAddVar(get_act->result_full);
} else if (auto icmp_act = std::dynamic_pointer_cast<ICMPAction>(act)) {
id_to_var.push_back(icmp_act->result_full);
var_to_id[icmp_act->result_full] = id_to_var.size() - 1;
TryAddVar(icmp_act->result_full);
;
} else if (auto call_act = std::dynamic_pointer_cast<CallItem>(act)) {
if (!std::holds_alternative<LLVMVOIDType>(call_act->return_type)) {
id_to_var.push_back(call_act->result_full);
var_to_id[call_act->result_full] = id_to_var.size() - 1;
TryAddVar(call_act->result_full);
}
} else if (auto select_act = std::dynamic_pointer_cast<SelectItem>(act)) {
id_to_var.push_back(select_act->result_full);
var_to_id[select_act->result_full] = id_to_var.size() - 1;
TryAddVar(select_act->result_full);
} else if (auto move_act = std::dynamic_pointer_cast<MoveInstruct>(act)) {
id_to_var.push_back(move_act->dest_full);
var_to_id[move_act->dest_full] = id_to_var.size() - 1;
TryAddVar(move_act->dest_full);
} else if (auto force_def_act = std::dynamic_pointer_cast<ForceDef>(act)) {
id_to_var.push_back(force_def_act->var_full);
var_to_id[force_def_act->var_full] = id_to_var.size() - 1;
TryAddVar(force_def_act->var_full);
} else if (auto load_spilled_args_act = std::dynamic_pointer_cast<LoadSpilledArgs>(act)) {
id_to_var.push_back(load_spilled_args_act->var_full);
var_to_id[load_spilled_args_act->var_full] = id_to_var.size() - 1;
TryAddVar(load_spilled_args_act->var_full);
} else if (auto alloca_act = std::dynamic_pointer_cast<AllocaAction>(act)) {
TryAddVar(alloca_act->name_full);
}
}
}
for (size_t i = 0; i < id_to_var.size(); i++) {
if (var_to_id.find(id_to_var[i]) == var_to_id.end())
throw std::runtime_error("var_to_id.find(id_to_var[i])==var_to_id.end()");
if (i != var_to_id[id_to_var[i]]) throw std::runtime_error("i!=var_to_id[id_to_var[i]]");
}
}
void UseDefCollect(CFGType &cfg, [[maybe_unused]] std::vector<std::string> &id_to_var,
@ -146,7 +151,7 @@ void UseDefCollect(CFGType &cfg, [[maybe_unused]] std::vector<std::string> &id_t
cur_act_def.push_back(var_to_id[select_act->result_full]);
}
} else if (auto move_act = std::dynamic_pointer_cast<MoveInstruct>(act)) {
if (var_to_id.find(move_act->src_full) != var_to_id.end()) {
if (VRegCheck(move_act->src_full) && var_to_id.find(move_act->src_full) != var_to_id.end()) {
cur_act_use.push_back(var_to_id[move_act->src_full]);
}
if (var_to_id.find(move_act->dest_full) != var_to_id.end()) {
@ -168,6 +173,8 @@ void UseDefCollect(CFGType &cfg, [[maybe_unused]] std::vector<std::string> &id_t
if (var_to_id.find(store_spilled_args_act->var_full) != var_to_id.end()) {
cur_act_use.push_back(var_to_id[store_spilled_args_act->var_full]);
}
} else if (auto alloca_act = std::dynamic_pointer_cast<AllocaAction>(act)) {
cur_act_def.push_back(var_to_id[alloca_act->name_full]);
}
std::sort(cur_act_use.begin(), cur_act_use.end());
std::sort(cur_act_def.begin(), cur_act_def.end());

View File

@ -11,6 +11,10 @@ void EnforcePhysicalRegs(CFGType &cfg) {
// process callee side
auto entry_node = cfg.entry;
auto func = cfg.corresponding_func;
std::unordered_set<std::string> missing_caller_saved_regs;
for (auto reg : caller_saved_regs) {
missing_caller_saved_regs.insert(reg);
}
for (size_t i = 0; i < 8 && i < func->args_full_name.size(); i++) {
auto new_def = std::make_shared<ForceDef>();
new_def->var_full = "%reg." + arg_regs[i];
@ -21,6 +25,7 @@ void EnforcePhysicalRegs(CFGType &cfg) {
new_move->ty = func->args[i];
entry_node->corresponding_block->actions.push_front(new_move);
entry_node->corresponding_block->actions.push_front(new_def);
missing_caller_saved_regs.erase(arg_regs[i]);
}
for (size_t i = 8; i < func->args_full_name.size(); i++) {
auto arg_load = std::make_shared<LoadSpilledArgs>();
@ -58,6 +63,7 @@ void EnforcePhysicalRegs(CFGType &cfg) {
new_move->src_full = std::dynamic_pointer_cast<RETAction>(block->exit_action)->value;
new_move->dest_full = "%reg.x10";
new_move->ty = std::dynamic_pointer_cast<RETAction>(block->exit_action)->type;
if (new_move->src_full == "%reg.x10" && new_move->dest_full == "%reg.x10") throw std::runtime_error("error");
block->actions.push_back(new_move);
std::dynamic_pointer_cast<RETAction>(block->exit_action)->value = "%reg.x10";
}
@ -82,6 +88,7 @@ void EnforcePhysicalRegs(CFGType &cfg) {
std::unordered_set<std::string> caller_saved_regs_to_process;
for (auto reg : caller_saved_regs) {
caller_saved_regs_to_process.insert(reg);
missing_caller_saved_regs.erase(reg);
}
for (size_t i = 0; i < call_act->args_val_full.size() & i < 8; i++) {
auto new_move = std::make_shared<MoveInstruct>();
@ -118,6 +125,16 @@ void EnforcePhysicalRegs(CFGType &cfg) {
--it_act;
}
}
// avoid missing some caller saved regs
for (auto reg : missing_caller_saved_regs) {
auto new_def = std::make_shared<ForceDef>();
new_def->var_full = "%reg." + reg;
new_def->ty = LLVMIRIntType(32);
auto new_use = std::make_shared<ForceUse>();
new_use->var_full = "%reg." + reg;
entry_node->corresponding_block->actions.push_front(new_use);
entry_node->corresponding_block->actions.push_front(new_def);
}
}
void ConductRegAllocForFunction(std::shared_ptr<FunctionDefItem> func) {
std::cerr << "processing function " << func->func_name_raw << std::endl;
@ -125,9 +142,12 @@ void ConductRegAllocForFunction(std::shared_ptr<FunctionDefItem> func) {
ConfGraph confgraph;
cfg = BuildCFGForFunction(func);
EnforcePhysicalRegs(cfg);
func->RecursivePrint(std::cerr);
do {
cfg.init();
cfg = BuildCFGForFunction(func);
LiveAnalysis(cfg);
confgraph.init();
confgraph = BuildConfGraph(cfg);
} while (ConductColoring(func, cfg, confgraph));
}