feat(backend): move coalescing via color preference and phi cycle breaking\n\nCollects move_preferences from MovReg instructions and uses them\nduring color selection to prefer the same physical register for\nmove-related virtual registers. Detects and breaks cycles in move\npreference chains to ensure correctness.

master
黄熙哲 1 week ago
parent 535a3c0122
commit 4bdca3f722

@ -642,7 +642,8 @@ namespace mir
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 std::set<int> &rematerializable_vregs,
const std::unordered_map<int, int> &move_preferences)
{
const int K = static_cast<int>(allocatable_regs.size());
GraphColoringResult result;
@ -788,8 +789,24 @@ namespace mir
}
int assigned_color = -1;
// 尝试使用 move 偏好颜色(如果偏好变量已分配且无冲突)
auto pref_it = move_preferences.find(v);
if (pref_it != move_preferences.end())
{
int pref_v = pref_it->second;
auto col_it = colored.find(pref_v);
if (col_it != colored.end())
{
int pref_color = col_it->second;
if (used_colors.find(pref_color) == used_colors.end())
assigned_color = pref_color;
}
}
// 第一遍:优先选 caller-saved 颜色 (c < caller_saved_threshold)
for (int c : allocatable_regs)
if (assigned_color < 0)
{
for (int c : allocatable_regs)
{
if (c >= caller_saved_threshold) break;
if (used_colors.find(c) == used_colors.end())
@ -811,6 +828,7 @@ namespace mir
}
}
}
}
if (assigned_color >= 0)
{
@ -1104,6 +1122,56 @@ namespace mir
rematerializable_vregs.insert(pair.first);
}
// 收集 MovReg 的 move 偏好映射
std::unordered_map<int, int> move_preferences;
for (auto &block : function.GetBlocks())
{
for (auto &inst : block->GetInstructions())
{
if (inst.GetOpcode() == Opcode::MovReg)
{
const auto &ops = inst.GetOperands();
if (ops.size() >= 2 &&
ops[0].GetKind() == Operand::Kind::VReg &&
ops[1].GetKind() == Operand::Kind::VReg)
{
int def_vreg = ops[0].GetVRegId();
int use_vreg = ops[1].GetVRegId();
if (function.GetVRegClass(def_vreg) == function.GetVRegClass(use_vreg))
move_preferences[def_vreg] = use_vreg;
}
}
}
}
// 检测并打破 move 偏好循环
{
std::unordered_set<int> visited;
for (auto &pair : move_preferences)
{
int cur = pair.first;
if (visited.count(cur)) continue;
std::unordered_set<int> path;
std::vector<int> chain;
int node = cur;
while (node != 0 && !visited.count(node))
{
visited.insert(node);
path.insert(node);
chain.push_back(node);
auto it = move_preferences.find(node);
if (it == move_preferences.end()) break;
int next = it->second;
if (path.count(next))
{
move_preferences.erase(chain.back());
break;
}
node = next;
}
}
}
std::vector<int> gp_alloc(GP_ALLOCATABLE, GP_ALLOCATABLE + GP_NUM_ALLOCATABLE);
std::vector<int> fp_alloc(FP_ALLOCATABLE, FP_ALLOCATABLE + FP_NUM_ALLOCATABLE);
@ -1113,10 +1181,10 @@ namespace mir
auto gp_result = ColorGraph(gp_graph, gp_alloc, function, 19,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs);
rematerializable_vregs, move_preferences);
auto fp_result = ColorGraph(fp_graph, fp_alloc, function, 16,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs);
rematerializable_vregs, move_preferences);
if (gp_result.spilled.empty() && fp_result.spilled.empty())
{
@ -1255,6 +1323,56 @@ namespace mir
rematerializable_vregs.insert(pair.first);
}
// 收集 MovReg 的 move 偏好映射
std::unordered_map<int, int> move_preferences;
for (auto &block : function.GetBlocks())
{
for (auto &inst : block->GetInstructions())
{
if (inst.GetOpcode() == Opcode::MovReg)
{
const auto &ops = inst.GetOperands();
if (ops.size() >= 2 &&
ops[0].GetKind() == Operand::Kind::VReg &&
ops[1].GetKind() == Operand::Kind::VReg)
{
int def_vreg = ops[0].GetVRegId();
int use_vreg = ops[1].GetVRegId();
if (function.GetVRegClass(def_vreg) == function.GetVRegClass(use_vreg))
move_preferences[def_vreg] = use_vreg;
}
}
}
}
// 检测并打破 move 偏好循环
{
std::unordered_set<int> visited;
for (auto &pair : move_preferences)
{
int cur = pair.first;
if (visited.count(cur)) continue;
std::unordered_set<int> path;
std::vector<int> chain;
int node = cur;
while (node != 0 && !visited.count(node))
{
visited.insert(node);
path.insert(node);
chain.push_back(node);
auto it = move_preferences.find(node);
if (it == move_preferences.end()) break;
int next = it->second;
if (path.count(next))
{
move_preferences.erase(chain.back());
break;
}
node = next;
}
}
}
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;
@ -1262,10 +1380,10 @@ 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);
rematerializable_vregs, move_preferences);
auto fp_result = ColorGraph(fp_graph, fp_alloc, function, 16,
liveness.interval_length, liveness.ref_count,
rematerializable_vregs);
rematerializable_vregs, move_preferences);
std::set<int> all_spilled = gp_result.spilled;
for (int v : fp_result.spilled)
all_spilled.insert(v);

Loading…
Cancel
Save