Skip to content

Commit 765bad1

Browse files
committed
fix: 回边携带空洞守卫仅作用于多定义值
之前的守卫用保守扩展段判“回边携带”,但保守段会因跨调用/递归等非循环 原因被大幅反向多填,把单定义值的菱形/布局空洞误判为携带空洞,阻止了安全合并。 真正的回边携带空洞必然来自“被回边重定义”的值(旧值经回边续命、精确段在前向 路径留洞),故只对多定义(defPositions>=2)的 owner 施加守卫。单定义值的空洞 只会是菱形分支边界或布局间隙(同值或确已死),跨越它合并安全。
1 parent 5b643e1 commit 765bad1

1 file changed

Lines changed: 9 additions & 3 deletions

File tree

backend/riscv64/RegCoalescer.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,14 @@ bool RegCoalescer::spansCarriedHole(const std::vector<Value *> & holedMembers,
272272
if (precIt == originalPrecise_.end()) {
273273
continue;
274274
}
275+
// 只有被多次定义(回边重定义)的值才可能产生回边携带空洞——旧值经回边
276+
// 续命而精确段在前向路径留洞。单定义值(循环不变量、i-1 之类)的空洞只会
277+
// 是菱形分支边界或布局间隙(同值或确已死),并非携带,跨越它合并安全。
278+
// 据此放行单定义 owner,避免误伤递归/菱形里的合并(如 knapsack 的 i-1)
279+
auto defIt = defPositions_.find(owner);
280+
if (defIt == defPositions_.end() || defIt->second.size() < 2) {
281+
continue;
282+
}
275283
const std::vector<Segment> ownSegs = normalizeSegments(precIt->second);
276284
if (ownSegs.size() < 2) {
277285
continue; // 该成员自身无空洞
@@ -280,8 +288,6 @@ bool RegCoalescer::spansCarriedHole(const std::vector<Value *> & holedMembers,
280288
const std::vector<Segment> & ownCons =
281289
consIt != conservativeSegments_.end() ? consIt->second : precIt->second;
282290

283-
auto defIt = defPositions_.find(owner);
284-
285291
// 逐个空洞(该成员自身相邻极大段之间的间隙)检查 spanner 段的插入方式
286292
for (size_t i = 0; i + 1 < ownSegs.size(); ++i) {
287293
const int gapStart = ownSegs[i].end;
@@ -291,7 +297,7 @@ bool RegCoalescer::spansCarriedHole(const std::vector<Value *> & holedMembers,
291297
}
292298
// 空洞末端是该值的新定义点:空洞前的旧值确已死亡,寄存器空闲,
293299
// 保守扩展只是反向多填了定义点前的循环体,并非回边携带,可放行
294-
if (defIt != defPositions_.end() && defIt->second.count(gapEnd) > 0) {
300+
if (defIt->second.count(gapEnd) > 0) {
295301
continue;
296302
}
297303
for (const auto & sp : spannerSegs) {

0 commit comments

Comments
 (0)