feat(backend): loop-depth weighted spill cost model\n\nAdds DFS-based back-edge detection to compute basic block loop\nnesting depth. Each vreg inherits the max loop depth of its\ndefining blocks. Spill cost multiplies interval+ref by 10^depth,\nmaking loop-carried variables much more expensive to spill.

master
黄熙哲 1 week ago
parent 993e81363a
commit 39b7e2ed19

@ -1,6 +1,7 @@
#include "mir/MIR.h"
#include <algorithm>
#include <functional>
#include <limits>
#include <queue>
#include <set>
@ -643,7 +644,8 @@ namespace mir
const std::unordered_map<int, int> &interval_length,
const std::unordered_map<int, int> &ref_count,
const std::set<int> &rematerializable_vregs,
const std::unordered_map<int, int> &move_preferences)
const std::unordered_map<int, int> &move_preferences,
const std::unordered_map<int, int> &vreg_loop_depth)
{
const int K = static_cast<int>(allocatable_regs.size());
GraphColoringResult result;
@ -903,8 +905,13 @@ namespace mir
auto rit = ref_count.find(v);
if (rit != ref_count.end()) ref = rit->second;
int d = degree[v];
// 可再物化变量MovImm 常量)大幅降权,优先 spill
int cost = len * 5 + ref * 15 - d * 25;
// 循环深度加权depth=0 → ×1, depth=1 → ×10, depth=2 → ×100
int depth = 0;
auto dit = vreg_loop_depth.find(v);
if (dit != vreg_loop_depth.end()) depth = dit->second;
int loop_mult = 1;
for (int i = 0; i < depth; i++) loop_mult *= 10;
int cost = (len * 5 + ref * 15) * loop_mult - d * 25;
if (rematerializable_vregs.count(v))
cost -= 100000;
return cost;
@ -1301,6 +1308,71 @@ namespace mir
auto liveness = ComputeBlockLiveness(function);
// === 回边检测:计算基本块的循环嵌套深度 ===
size_t num_blocks = function.GetBlocks().size();
std::vector<int> loop_depth(num_blocks, 0);
{
std::unordered_map<int, size_t> blk_label_to_idx;
for (size_t i = 0; i < liveness.block_liveness.size(); ++i)
blk_label_to_idx[function.GetBlocks()[i]->GetLabelId()] = i;
std::vector<int> dfs_state(num_blocks, 0); // 0=未访问, 1=栈中, 2=已完成
std::function<void(size_t)> dfs = [&](size_t cur) {
dfs_state[cur] = 1;
const auto &insts = function.GetBlocks()[cur]->GetInstructions();
for (const auto &inst : insts)
{
size_t succ = static_cast<size_t>(-1);
if (inst.GetOpcode() == Opcode::Br && inst.GetOperands().size() >= 1 &&
inst.GetOperands()[0].GetKind() == Operand::Kind::Label)
{
auto it = blk_label_to_idx.find(inst.GetOperands()[0].GetLabel());
if (it != blk_label_to_idx.end()) succ = it->second;
}
if (inst.GetOpcode() == Opcode::CondBr && inst.GetOperands().size() >= 2 &&
inst.GetOperands()[1].GetKind() == Operand::Kind::Label)
{
auto it = blk_label_to_idx.find(inst.GetOperands()[1].GetLabel());
if (it != blk_label_to_idx.end()) succ = it->second;
}
if (succ == static_cast<size_t>(-1)) continue;
if (dfs_state[succ] == 1)
{
// 回边cur → succ 且 succ 在栈中
loop_depth[succ]++;
loop_depth[cur]++;
}
else if (dfs_state[succ] == 0)
{
dfs(succ);
if (loop_depth[succ] > 0)
loop_depth[cur] = std::max(loop_depth[cur], loop_depth[succ]);
}
}
dfs_state[cur] = 2;
};
dfs(0);
}
// 为每个 vreg 确定其最大循环深度(取定义所在块的 loop_depth
std::unordered_map<int, int> vreg_loop_depth;
for (size_t bi = 0; bi < num_blocks; ++bi)
{
const auto &insts = function.GetBlocks()[bi]->GetInstructions();
for (const auto &inst : insts)
{
auto du = GetInstDefUse(inst, function);
for (int d : du.defs)
{
auto it = vreg_loop_depth.find(d);
int cur_depth = loop_depth[bi];
if (it == vreg_loop_depth.end() || cur_depth > it->second)
vreg_loop_depth[d] = cur_depth;
}
}
}
// 构建可再物化 vreg 集合MovImm 常量)
std::set<int> rematerializable_vregs;
for (const auto &pair : vreg_def_inst)
@ -1368,10 +1440,12 @@ namespace mir
auto gp_result = ColorGraph(gp_graph, gp_alloc, function, 19,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs, move_preferences);
rematerializable_vregs, move_preferences,
vreg_loop_depth);
auto fp_result = ColorGraph(fp_graph, fp_alloc, function, 16,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs, move_preferences);
rematerializable_vregs, move_preferences,
vreg_loop_depth);
if (gp_result.spilled.empty() && fp_result.spilled.empty())
{
@ -1524,6 +1598,69 @@ namespace mir
auto liveness = ComputeBlockLiveness(function);
// === 回边检测:计算基本块的循环嵌套深度 ===
size_t num_blocks = function.GetBlocks().size();
std::vector<int> loop_depth(num_blocks, 0);
{
std::unordered_map<int, size_t> blk_label_to_idx;
for (size_t i = 0; i < liveness.block_liveness.size(); ++i)
blk_label_to_idx[function.GetBlocks()[i]->GetLabelId()] = i;
std::vector<int> dfs_state(num_blocks, 0);
std::function<void(size_t)> dfs = [&](size_t cur) {
dfs_state[cur] = 1;
const auto &insts = function.GetBlocks()[cur]->GetInstructions();
for (const auto &inst : insts)
{
size_t succ = static_cast<size_t>(-1);
if (inst.GetOpcode() == Opcode::Br && inst.GetOperands().size() >= 1 &&
inst.GetOperands()[0].GetKind() == Operand::Kind::Label)
{
auto it = blk_label_to_idx.find(inst.GetOperands()[0].GetLabel());
if (it != blk_label_to_idx.end()) succ = it->second;
}
if (inst.GetOpcode() == Opcode::CondBr && inst.GetOperands().size() >= 2 &&
inst.GetOperands()[1].GetKind() == Operand::Kind::Label)
{
auto it = blk_label_to_idx.find(inst.GetOperands()[1].GetLabel());
if (it != blk_label_to_idx.end()) succ = it->second;
}
if (succ == static_cast<size_t>(-1)) continue;
if (dfs_state[succ] == 1)
{
loop_depth[succ]++;
loop_depth[cur]++;
}
else if (dfs_state[succ] == 0)
{
dfs(succ);
if (loop_depth[succ] > 0)
loop_depth[cur] = std::max(loop_depth[cur], loop_depth[succ]);
}
}
dfs_state[cur] = 2;
};
dfs(0);
}
std::unordered_map<int, int> vreg_loop_depth;
for (size_t bi = 0; bi < num_blocks; ++bi)
{
const auto &insts = function.GetBlocks()[bi]->GetInstructions();
for (const auto &inst : insts)
{
auto du = GetInstDefUse(inst, function);
for (int d : du.defs)
{
auto it = vreg_loop_depth.find(d);
int cur_depth = loop_depth[bi];
if (it == vreg_loop_depth.end() || cur_depth > it->second)
vreg_loop_depth[d] = cur_depth;
}
}
}
// 构建可再物化 vreg 集合
std::set<int> rematerializable_vregs;
for (const auto &pair : vreg_def_inst)
@ -1589,10 +1726,12 @@ namespace mir
BuildInterferenceForFP(function, liveness.block_liveness, fp_alloc, fp_graph);
auto gp_result = ColorGraph(gp_graph, gp_alloc, function, 19,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs, move_preferences);
rematerializable_vregs, move_preferences,
vreg_loop_depth);
auto fp_result = ColorGraph(fp_graph, fp_alloc, function, 16,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs, move_preferences);
rematerializable_vregs, move_preferences,
vreg_loop_depth);
std::set<int> all_spilled = gp_result.spilled;
for (int v : fp_result.spilled)
all_spilled.insert(v);

@ -21,66 +21,66 @@
| 测试集标识 | 源基线(行) | 当前(行) | 备注 |
|---|---|---|---|
| performance/01_mm1 | 335 | 313 | 比源基线少22行 | 比源基线少8行 | |
| performance/01_mm2 | 335 | 313 | 比源基线少22行 | 比源基线少8行 | |
| performance/01_mm3 | 335 | 313 | 比源基线少22行 | 比源基线少8行 | |
| performance/03_sort1 | 668 | 640 | 比源基线少28行 | 比源基线少14行 | |
| performance/03_sort2 | 668 | 640 | 比源基线少28行 | 比源基线少14行 | |
| performance/03_sort3 | 668 | 640 | 比源基线少28行 | 比源基线少14行 | |
| performance/conv2d-1 | 752 | 657 | 比源基线少95行 | 比源基线少20行 | |
| performance/conv2d-2 | 752 | 657 | 比源基线少95行 | 比源基线少20行 | |
| performance/conv2d-3 | 752 | 657 | 比源基线少95行 | 比源基线少20行 | |
| performance/crc1 | 328 | 290 | 比源基线少38行 | 比源基线少10行 | |
| performance/crc2 | 328 | 290 | 比源基线少38行 | 比源基线少10行 | |
| performance/crc3 | 328 | 290 | 比源基线少38行 | 比源基线少10行 | |
| performance/crypto-1 | 1967 | 1949 | 比源基线少18行 | 比源基线少14行 | |
| performance/crypto-2 | 1967 | 1949 | 比源基线少18行 | 比源基线少14行 | |
| performance/crypto-3 | 1967 | 1949 | 比源基线少18行 | 比源基线少14行 | |
| performance/fft0 | 658 | 619 | 比源基线少39行 | 比源基线少30行 | |
| performance/fft1 | 658 | 619 | 比源基线少39行 | 比源基线少30行 | |
| performance/fft2 | 658 | 619 | 比源基线少39行 | 比源基线少30行 | |
| performance/h-1-01 | 162 | 158 | 比源基线少4行 | 比源基线少2行 | |
| performance/h-1-02 | 162 | 158 | 比源基线少4行 | 比源基线少2行 | |
| performance/h-1-03 | 162 | 158 | 比源基线少4行 | 比源基线少2行 | |
| performance/h-10-01 | 349 | 335 | 比源基线少14行 | 比源基线少6行 | |
| performance/h-10-02 | 349 | 335 | 比源基线少14行 | 比源基线少6行 | |
| performance/h-10-03 | 349 | 335 | 比源基线少14行 | 比源基线少6行 | |
| performance/h-4-01 | 173 | 163 | 比源基线少10行 | 比源基线少6行 | |
| performance/h-4-02 | 173 | 163 | 比源基线少10行 | 比源基线少6行 | |
| performance/h-4-03 | 173 | 163 | 比源基线少10行 | 比源基线少6行 | |
| performance/h-5-01 | 352 | 349 | 比源基线少3行 | 比源基线少10行 | |
| performance/h-5-02 | 352 | 349 | 比源基线少3行 | 比源基线少10行 | |
| performance/h-5-03 | 352 | 349 | 比源基线少3行 | 比源基线少10行 | |
| performance/h-8-01 | 504 | 502 | 比源基线少2行 | 比源基线少2行 | |
| performance/h-8-02 | 504 | 502 | 比源基线少2行 | 比源基线少2行 | |
| performance/h-8-03 | 504 | 502 | 比源基线少2行 | 比源基线少2行 | |
| performance/h-9-01 | 239 | 227 | 比源基线少12行 | 比源基线少2行 | |
| performance/h-9-02 | 239 | 227 | 比源基线少12行 | 比源基线少2行 | |
| performance/h-9-03 | 239 | 227 | 比源基线少12行 | 比源基线少2行 | |
| performance/huffman-01 | 893 | 849 | 比源基线少44行 | 比源基线少14行 | |
| performance/huffman-02 | 893 | 849 | 比源基线少44行 | 比源基线少14行 | |
| performance/huffman-03 | 893 | 849 | 比源基线少44行 | 比源基线少14行 | |
| performance/knapsack_naive-1 | 185 | 175 | 比源基线少10行 | 比源基线少10行 | |
| performance/knapsack_naive-2 | 185 | 175 | 比源基线少10行 | 比源基线少10行 | |
| performance/knapsack_naive-3 | 185 | 175 | 比源基线少10行 | 比源基线少10行 | |
| performance/01_mm1 | 335 | 313 | 比源基线少22行 | 比源基线少22行 | 比源基线少8行 | |
| performance/01_mm2 | 335 | 313 | 比源基线少22行 | 比源基线少22行 | 比源基线少8行 | |
| performance/01_mm3 | 335 | 313 | 比源基线少22行 | 比源基线少22行 | 比源基线少8行 | |
| performance/03_sort1 | 668 | 640 | 比源基线少28行 | 比源基线少28行 | 比源基线少14行 | |
| performance/03_sort2 | 668 | 640 | 比源基线少28行 | 比源基线少28行 | 比源基线少14行 | |
| performance/03_sort3 | 668 | 640 | 比源基线少28行 | 比源基线少28行 | 比源基线少14行 | |
| performance/conv2d-1 | 752 | 657 | 比源基线少95行 | 比源基线少95行 | 比源基线少20行 | |
| performance/conv2d-2 | 752 | 657 | 比源基线少95行 | 比源基线少95行 | 比源基线少20行 | |
| performance/conv2d-3 | 752 | 657 | 比源基线少95行 | 比源基线少95行 | 比源基线少20行 | |
| performance/crc1 | 328 | 290 | 比源基线少38行 | 比源基线少38行 | 比源基线少10行 | |
| performance/crc2 | 328 | 290 | 比源基线少38行 | 比源基线少38行 | 比源基线少10行 | |
| performance/crc3 | 328 | 290 | 比源基线少38行 | 比源基线少38行 | 比源基线少10行 | |
| performance/crypto-1 | 1967 | 1949 | 比源基线少18行 | 比源基线少18行 | 比源基线少14行 | |
| performance/crypto-2 | 1967 | 1949 | 比源基线少18行 | 比源基线少18行 | 比源基线少14行 | |
| performance/crypto-3 | 1967 | 1949 | 比源基线少18行 | 比源基线少18行 | 比源基线少14行 | |
| performance/fft0 | 658 | 619 | 比源基线少39行 | 比源基线少39行 | 比源基线少30行 | |
| performance/fft1 | 658 | 619 | 比源基线少39行 | 比源基线少39行 | 比源基线少30行 | |
| performance/fft2 | 658 | 619 | 比源基线少39行 | 比源基线少39行 | 比源基线少30行 | |
| performance/h-1-01 | 162 | 158 | 比源基线少4行 | 比源基线少4行 | 比源基线少2行 | |
| performance/h-1-02 | 162 | 158 | 比源基线少4行 | 比源基线少4行 | 比源基线少2行 | |
| performance/h-1-03 | 162 | 158 | 比源基线少4行 | 比源基线少4行 | 比源基线少2行 | |
| performance/h-10-01 | 349 | 335 | 比源基线少14行 | 比源基线少14行 | 比源基线少6行 | |
| performance/h-10-02 | 349 | 335 | 比源基线少14行 | 比源基线少14行 | 比源基线少6行 | |
| performance/h-10-03 | 349 | 335 | 比源基线少14行 | 比源基线少14行 | 比源基线少6行 | |
| performance/h-4-01 | 173 | 163 | 比源基线少10行 | 比源基线少10行 | 比源基线少6行 | |
| performance/h-4-02 | 173 | 163 | 比源基线少10行 | 比源基线少10行 | 比源基线少6行 | |
| performance/h-4-03 | 173 | 163 | 比源基线少10行 | 比源基线少10行 | 比源基线少6行 | |
| performance/h-5-01 | 352 | 349 | 比源基线少3行 | 比源基线少3行 | 比源基线少10行 | |
| performance/h-5-02 | 352 | 349 | 比源基线少3行 | 比源基线少3行 | 比源基线少10行 | |
| performance/h-5-03 | 352 | 349 | 比源基线少3行 | 比源基线少3行 | 比源基线少10行 | |
| performance/h-8-01 | 504 | 502 | 比源基线少2行 | 比源基线少2行 | 比源基线少2行 | |
| performance/h-8-02 | 504 | 502 | 比源基线少2行 | 比源基线少2行 | 比源基线少2行 | |
| performance/h-8-03 | 504 | 502 | 比源基线少2行 | 比源基线少2行 | 比源基线少2行 | |
| performance/h-9-01 | 239 | 227 | 比源基线少12行 | 比源基线少12行 | 比源基线少2行 | |
| performance/h-9-02 | 239 | 227 | 比源基线少12行 | 比源基线少12行 | 比源基线少2行 | |
| performance/h-9-03 | 239 | 227 | 比源基线少12行 | 比源基线少12行 | 比源基线少2行 | |
| performance/huffman-01 | 893 | 849 | 比源基线少44行 | 比源基线少44行 | 比源基线少14行 | |
| performance/huffman-02 | 893 | 849 | 比源基线少44行 | 比源基线少44行 | 比源基线少14行 | |
| performance/huffman-03 | 893 | 849 | 比源基线少44行 | 比源基线少44行 | 比源基线少14行 | |
| performance/knapsack_naive-1 | 185 | 175 | 比源基线少10行 | 比源基线少10行 | 比源基线少10行 | |
| performance/knapsack_naive-2 | 185 | 175 | 比源基线少10行 | 比源基线少10行 | 比源基线少10行 | |
| performance/knapsack_naive-3 | 185 | 175 | 比源基线少10行 | 比源基线少10行 | 比源基线少10行 | |
| performance/many_mat_cal-1 | 523 | 523 | |
| performance/many_mat_cal-2 | 523 | 523 | |
| performance/many_mat_cal-3 | 523 | 523 | |
| performance/matmul1 | 450 | 450 | |
| performance/matmul2 | 450 | 450 | |
| performance/matmul3 | 450 | 450 | |
| performance/optimization_scheduling1 | 136 | 122 | 比源基线少14行 | 比源基线少6行 | |
| performance/optimization_scheduling2 | 136 | 122 | 比源基线少14行 | 比源基线少6行 | |
| performance/optimization_scheduling3 | 136 | 122 | 比源基线少14行 | 比源基线少6行 | |
| performance/shuffle0 | 485 | 472 | 比源基线少13行 | 比源基线少6行 | |
| performance/shuffle1 | 485 | 472 | 比源基线少13行 | 比源基线少6行 | |
| performance/shuffle2 | 485 | 472 | 比源基线少13行 | 比源基线少6行 | |
| performance/sl1 | 283 | 280 | 比源基线少3行 | 比源基线少8行 | |
| performance/sl2 | 283 | 280 | 比源基线少3行 | 比源基线少8行 | |
| performance/sl3 | 283 | 280 | 比源基线少3行 | 比源基线少8行 | |
| performance/transpose0 | 225 | 211 | 比源基线少14行 | 比源基线少4行 | |
| performance/transpose1 | 225 | 211 | 比源基线少14行 | 比源基线少4行 | |
| performance/transpose2 | 225 | 211 | 比源基线少14行 | 比源基线少4行 | |
| performance/optimization_scheduling1 | 136 | 122 | 比源基线少14行 | 比源基线少14行 | 比源基线少6行 | |
| performance/optimization_scheduling2 | 136 | 122 | 比源基线少14行 | 比源基线少14行 | 比源基线少6行 | |
| performance/optimization_scheduling3 | 136 | 122 | 比源基线少14行 | 比源基线少14行 | 比源基线少6行 | |
| performance/shuffle0 | 485 | 472 | 比源基线少13行 | 比源基线少13行 | 比源基线少6行 | |
| performance/shuffle1 | 485 | 472 | 比源基线少13行 | 比源基线少13行 | 比源基线少6行 | |
| performance/shuffle2 | 485 | 472 | 比源基线少13行 | 比源基线少13行 | 比源基线少6行 | |
| performance/sl1 | 283 | 280 | 比源基线少3行 | 比源基线少3行 | 比源基线少8行 | |
| performance/sl2 | 283 | 280 | 比源基线少3行 | 比源基线少3行 | 比源基线少8行 | |
| performance/sl3 | 283 | 280 | 比源基线少3行 | 比源基线少3行 | 比源基线少8行 | |
| performance/transpose0 | 225 | 211 | 比源基线少14行 | 比源基线少14行 | 比源基线少4行 | |
| performance/transpose1 | 225 | 211 | 比源基线少14行 | 比源基线少14行 | 比源基线少4行 | |
| performance/transpose2 | 225 | 211 | 比源基线少14行 | 比源基线少14行 | 比源基线少4行 | |
## 统计

Loading…
Cancel
Save