From 11b9f31b7afca0fdd64030860b2b15119b0dea54 Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Mon, 21 Oct 2024 06:08:16 +0000 Subject: [PATCH] finish preparations for coloring --- include/opt/cfg.h | 14 +++++++- include/opt/confgraph.h | 27 ++++++++++---- src/opt/confgraph.cpp | 78 +++++++++++++++++++++++++++++++++++++++-- src/opt/regalloc.cpp | 14 +++----- 4 files changed, 113 insertions(+), 20 deletions(-) diff --git a/include/opt/cfg.h b/include/opt/cfg.h index 3cb2dc9..f5e10c2 100644 --- a/include/opt/cfg.h +++ b/include/opt/cfg.h @@ -149,4 +149,16 @@ bool GetCollectionsIsSame(const Container &a, const Container &b, Compare comp = return ita == a.end() && itb == b.end(); } -CFGType BuildCFGForFunction(const std::shared_ptr &func); \ No newline at end of file +CFGType BuildCFGForFunction(const std::shared_ptr &func); + +// RISC-V calling convention compatible +const static std::vector held_tmp_regs = {"x28", "x29", "x30", "x31"}; +const static std::string zero = "x0", sp = "x2", ra = "x1", fp = "x8"; +const static std::vector callee_saved_regs = {"x3", "x4", "x9", "x18", "x19", "x20", "x21", + "x22", "x23", "x24", "x25", "x26", "x27"}; +const static std::vector caller_saved_regs = {"x5", "x6", "x7", "x10", "x11", "x12", + "x13", "x14", "x15", "x16", "x17"}; +const static std::vector arg_regs = {"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"}; +const static std::vector 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"}; \ No newline at end of file diff --git a/include/opt/confgraph.h b/include/opt/confgraph.h index 84f1644..e748033 100644 --- a/include/opt/confgraph.h +++ b/include/opt/confgraph.h @@ -3,19 +3,32 @@ #include "cfg.h" class ConfGraphNode { public: - std::string var_name; + const static size_t kInf = (std::numeric_limits::max()) >> 2; + std::vector var_ids; size_t color; - bool is_move_related; - bool move_related_but_frozen; + size_t degree; bool is_binded_with_physical_reg; - std::vector neighbors; - ConfGraphNode(std::string var_name) : var_name(var_name) {} + std::list neighbors; + std::list move_neighbors; + ConfGraphNode() = default; }; class ConfGraph { public: - std::unordered_map name_to_node; + // available after construction + std::unordered_map id_to_node; std::vector> nodes; + std::unordered_map::iterator>> + adj_table; + + // available during coloring + std::vector stack; + std::vector actual_spills; + std::unordered_set low_degree_and_not_move_related; + std::unordered_set low_degree_and_move_related; + std::unordered_set high_degree_nodes; + std::unordered_set pending_moves; + std::unordered_set potential_moves; }; ConfGraph BuildConfGraph(CFGType &cfg); -bool TryColoring(std::shared_ptr src, CFGType &cfg, ConfGraph& confgraph); \ No newline at end of file +bool ConductColoring(std::shared_ptr src, CFGType &cfg, ConfGraph &confgraph); \ No newline at end of file diff --git a/src/opt/confgraph.cpp b/src/opt/confgraph.cpp index 664ad86..5ea502d 100644 --- a/src/opt/confgraph.cpp +++ b/src/opt/confgraph.cpp @@ -1,6 +1,80 @@ #include "confgraph.h" +#include +#include +#include #include +#include #include "cfg.h" +ConfGraph BuildConfGraph(CFGType &cfg) { + std::unordered_map> edges; + ConfGraph res; + for (size_t id = 0; id < cfg.id_to_var.size(); id++) { + auto node = std::make_shared(); + 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 src, CFGType &cfg, ConfGraph &confgraph) { + confgraph.stack.clear(); + confgraph.actual_spills.clear(); -ConfGraph BuildConfGraph(CFGType &cfg) { ; } -bool TryColoring(std::shared_ptr src, CFGType &cfg, ConfGraph& confgraph) { return false; } + confgraph.low_degree_and_not_move_related.clear(); + 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 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; +} \ No newline at end of file diff --git a/src/opt/regalloc.cpp b/src/opt/regalloc.cpp index 381a107..1692898 100644 --- a/src/opt/regalloc.cpp +++ b/src/opt/regalloc.cpp @@ -6,14 +6,6 @@ #include "phieliminate.h" #include "tools.h" -// RISC-V calling convention compatible -static std::vector held_tmp_regs = {"x28", "x29", "x30", "x31"}; -static std::vector callee_saved_regs = {"x3", "x4", "x9", "x18", "x19", "x20", "x21", - "x22", "x23", "x24", "x25", "x26", "x27"}; -static std::vector caller_saved_regs = {"x5", "x6", "x7", "x10", "x11", "x12", - "x13", "x14", "x15", "x16", "x17"}; -static std::vector 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) { using namespace opt; // process callee side @@ -128,14 +120,16 @@ void EnforcePhysicalRegs(CFGType &cfg) { } } void ConductRegAllocForFunction(std::shared_ptr func) { + std::cerr << "processing function " << func->func_name_raw << std::endl; CFGType cfg; ConfGraph confgraph; + cfg = BuildCFGForFunction(func); + EnforcePhysicalRegs(cfg); do { cfg = BuildCFGForFunction(func); - EnforcePhysicalRegs(cfg); LiveAnalysis(cfg); confgraph = BuildConfGraph(cfg); - } while (TryColoring(func, cfg, confgraph)); + } while (ConductColoring(func, cfg, confgraph)); } std::shared_ptr RegAlloc(std::shared_ptr src) {