feat(backend): interval-length weighted spill cost model for graph coloring\n\nReplace degree-only spill selection with weighted cost model:\ncost = interval_length * 5 + ref_count * 15 - degree * 25\nLower cost spills first. Rematerializable constants get -100000 bonus.

master
黄熙哲 1 week ago
parent c84458daed
commit 4fad027da8

@ -1,6 +1,7 @@
#include "mir/MIR.h"
#include <algorithm>
#include <limits>
#include <queue>
#include <set>
#include <unordered_map>
@ -606,7 +607,10 @@ namespace mir
InterferenceGraph &graph,
const std::vector<int> &allocatable_regs,
MachineFunction & /*function*/,
int caller_saved_threshold = 19)
int caller_saved_threshold,
const std::unordered_map<int, int> &interval_length,
const std::unordered_map<int, int> &ref_count,
const std::set<int> &rematerializable_vregs)
{
const int K = static_cast<int>(allocatable_regs.size());
GraphColoringResult result;
@ -687,13 +691,32 @@ namespace mir
if (!remaining.empty())
{
// spill cost: len(活跃指令数)*5 + ref(def+use总次数)*15 - degree(干涉度数)*25
// cost 越小越优先 spill —— 短区间、少引用、高冲突的变量更适合溢出
// 权重基于经验调节degree 项主导len/ref 项作为 tiebreaker
auto GetSpillCost = [&](int v) -> int {
int len = 0;
auto lit = interval_length.find(v);
if (lit != interval_length.end()) len = lit->second;
int ref = 0;
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;
if (rematerializable_vregs.count(v))
cost -= 100000;
return cost;
};
int spill_candidate = -1;
int max_degree = -1;
int min_cost = std::numeric_limits<int>::max();
for (int v : remaining)
{
if (degree[v] > max_degree)
int cost = GetSpillCost(v);
if (cost < min_cost)
{
max_degree = degree[v];
min_cost = cost;
spill_candidate = v;
}
}
@ -1041,6 +1064,14 @@ namespace mir
auto liveness = ComputeBlockLiveness(function);
// 构建可再物化 vreg 集合MovImm 常量)
std::set<int> rematerializable_vregs;
for (const auto &pair : vreg_def_inst)
{
if (pair.second->IsRematerializable())
rematerializable_vregs.insert(pair.first);
}
std::vector<int> gp_alloc(GP_ALLOCATABLE, GP_ALLOCATABLE + GP_NUM_ALLOCATABLE);
std::vector<int> fp_alloc(FP_ALLOCATABLE, FP_ALLOCATABLE + FP_NUM_ALLOCATABLE);
@ -1048,8 +1079,12 @@ namespace mir
BuildInterferenceForGP(function, liveness.block_liveness, gp_alloc, gp_graph);
BuildInterferenceForFP(function, liveness.block_liveness, fp_alloc, fp_graph);
auto gp_result = ColorGraph(gp_graph, gp_alloc, function, 19);
auto fp_result = ColorGraph(fp_graph, fp_alloc, function, 16);
auto gp_result = ColorGraph(gp_graph, gp_alloc, function, 19,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs);
auto fp_result = ColorGraph(fp_graph, fp_alloc, function, 16,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs);
if (gp_result.spilled.empty() && fp_result.spilled.empty())
{
@ -1179,13 +1214,26 @@ namespace mir
}
auto liveness = ComputeBlockLiveness(function);
// 构建可再物化 vreg 集合
std::set<int> rematerializable_vregs;
for (const auto &pair : vreg_def_inst)
{
if (pair.second->IsRematerializable())
rematerializable_vregs.insert(pair.first);
}
std::vector<int> gp_alloc(GP_ALLOCATABLE, GP_ALLOCATABLE + GP_NUM_ALLOCATABLE);
std::vector<int> fp_alloc(FP_ALLOCATABLE, FP_ALLOCATABLE + FP_NUM_ALLOCATABLE);
InterferenceGraph gp_graph, fp_graph;
BuildInterferenceForGP(function, liveness.block_liveness, gp_alloc, gp_graph);
BuildInterferenceForFP(function, liveness.block_liveness, fp_alloc, fp_graph);
auto gp_result = ColorGraph(gp_graph, gp_alloc, function, 19);
auto fp_result = ColorGraph(fp_graph, fp_alloc, function, 16);
auto gp_result = ColorGraph(gp_graph, gp_alloc, function, 19,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs);
auto fp_result = ColorGraph(fp_graph, fp_alloc, function, 16,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs);
std::set<int> all_spilled = gp_result.spilled;
for (int v : fp_result.spilled)
all_spilled.insert(v);

Loading…
Cancel
Save