@ -98,6 +98,7 @@ bool RISCv64RegAlloc::doAllocation() {
precolorByCallingConvention ( ) ;
analyzeLiveness ( ) ;
build ( ) ;
protectCrossCallVRegs ( ) ;
makeWorklist ( ) ;
while ( ! simplifyWorklist . empty ( ) | | ! worklistMoves . empty ( ) | | ! freezeWorklist . empty ( ) | | ! spillWorklist . empty ( ) ) {
@ -185,6 +186,57 @@ void RISCv64RegAlloc::precolorByCallingConvention() {
}
}
void RISCv64RegAlloc : : protectCrossCallVRegs ( ) {
// 从ISel获取被标记为需要保护的参数副本vreg集合
const auto & vregs_to_protect_potentially = MFunc - > getProtectedArgumentVRegs ( ) ;
if ( vregs_to_protect_potentially . empty ( ) ) {
return ; // 如果没有需要保护的vreg, 直接返回
}
VRegSet live_across_call_vregs ;
// 遍历所有指令, 找出哪些被标记的vreg其生命周期确实跨越了call指令
for ( const auto & mbb_ptr : MFunc - > getBlocks ( ) ) {
for ( const auto & instr_ptr : mbb_ptr - > getInstructions ( ) ) {
if ( instr_ptr - > getOpcode ( ) = = RVOpcodes : : CALL ) {
const VRegSet & live_out_after_call = live_out_map . at ( instr_ptr . get ( ) ) ;
for ( unsigned vreg : vregs_to_protect_potentially ) {
if ( live_out_after_call . count ( vreg ) ) {
live_across_call_vregs . insert ( vreg ) ;
}
}
}
}
}
if ( live_across_call_vregs . empty ( ) ) {
return ; // 如果被标记的vreg没有一个跨越call, 也无需操作
}
if ( DEEPDEBUG ) {
std : : cerr < < " --- [FIX] Applying protection for argument vregs that live across calls: " ;
for ( unsigned v : live_across_call_vregs ) std : : cerr < < regIdToString ( v ) < < " " ;
std : : cerr < < " \n " ;
}
// 获取所有调用者保存寄存器
const auto & caller_saved_int = getCallerSavedIntRegs ( ) ;
const auto & caller_saved_fp = getCallerSavedFpRegs ( ) ;
const unsigned offset = static_cast < unsigned > ( PhysicalReg : : PHYS_REG_START_ID ) ;
// 为每个确认跨越call的vreg, 添加与所有调用者保存寄存器的冲突
for ( unsigned vreg : live_across_call_vregs ) {
if ( isFPVReg ( vreg ) ) { // 如果是浮点vreg
for ( auto preg : caller_saved_fp ) {
addEdge ( vreg , offset + static_cast < unsigned > ( preg ) ) ;
}
} else { // 如果是整数vreg
for ( auto preg : caller_saved_int ) {
addEdge ( vreg , offset + static_cast < unsigned > ( preg ) ) ;
}
}
}
}
// 初始化/重置所有数据结构
void RISCv64RegAlloc : : initialize ( ) {
initial . clear ( ) ;
@ -504,12 +556,20 @@ void RISCv64RegAlloc::coalesce() {
unsigned y = getAlias ( * use . begin ( ) ) ;
unsigned u , v ;
// 进一步修正: 标准化u和v的逻辑, 必须同时考虑物理寄存器和已预着色的虚拟寄存器 。
// 目标是确保如果两个操作数中有一个是预着色的,它一定会被赋给 u 。
if ( precolored . count ( y ) | | coloredNodes . count ( y ) ) {
u = y ; v = x ;
} else {
u = x ; v = y ;
// 总是将待合并的虚拟寄存器赋给 v, 将合并目标赋给 u 。
// 优先级: 物理寄存器 (precolored) > 已着色的虚拟寄存器 (coloredNodes) > 普通虚拟寄存器 。
if ( precolored . count ( y ) ) {
u = y ;
v = x ;
} else if ( precolored . count ( x ) ) {
u = x ;
v = y ;
} else if ( coloredNodes . count ( y ) ) {
u = y ;
v = x ;
} else {
u = x ;
v = y ;
}
// 防御性检查,处理物理寄存器之间的传送指令
@ -528,7 +588,75 @@ void RISCv64RegAlloc::coalesce() {
addWorklist ( u ) ;
return ;
}
bool is_conflicting = false ;
// 检查1: u 和 v 在冲突图中是否直接相连
if ( ( adjList . count ( v ) & & adjList . at ( v ) . count ( u ) ) | | ( adjList . count ( u ) & & adjList . at ( u ) . count ( v ) ) ) {
if ( DEEPERDEBUG ) std : : cerr < < " -> [Check] Nodes interfere directly. \n " ;
is_conflicting = true ;
}
// 检查2: 如果节点不直接相连, 则检查是否存在间接的颜色冲突
else {
// 获取 u 和 v 的颜色(如果它们有的话)
unsigned u_color_id = 0 , v_color_id = 0 ;
if ( precolored . count ( u ) ) {
u_color_id = u ;
} else if ( coloredNodes . count ( u ) | | color_map . count ( u ) ) { // color_map.count(u) 是更可靠的检查
u_color_id = static_cast < unsigned > ( PhysicalReg : : PHYS_REG_START_ID ) + static_cast < unsigned > ( color_map . at ( u ) ) ;
}
if ( precolored . count ( v ) ) {
v_color_id = v ;
} else if ( coloredNodes . count ( v ) | | color_map . count ( v ) ) {
v_color_id = static_cast < unsigned > ( PhysicalReg : : PHYS_REG_START_ID ) + static_cast < unsigned > ( color_map . at ( v ) ) ;
}
// 如果 u 有颜色,检查 v 是否与该颜色代表的物理寄存器冲突
if ( u_color_id ! = 0 & & adjList . count ( v ) & & adjList . at ( v ) . count ( u_color_id ) ) {
if ( DEEPERDEBUG ) std : : cerr < < " -> [Check] Node " < < regIdToString ( v ) < < " interferes with the color of " < < regIdToString ( u ) < < " ( " < < regIdToString ( u_color_id ) < < " ). \n " ;
is_conflicting = true ;
}
// 如果 v 有颜色,检查 u 是否与该颜色代表的物理寄存器冲突
else if ( v_color_id ! = 0 & & adjList . count ( u ) & & adjList . at ( u ) . count ( v_color_id ) ) {
if ( DEEPERDEBUG ) std : : cerr < < " -> [Check] Node " < < regIdToString ( u ) < < " interferes with the color of " < < regIdToString ( v ) < < " ( " < < regIdToString ( v_color_id ) < < " ). \n " ;
is_conflicting = true ;
}
}
if ( is_conflicting ) {
if ( DEEPERDEBUG ) std : : cerr < < " -> Constrained (nodes interfere directly or via pre-coloring). \n " ;
constrainedMoves . insert ( move ) ;
addWorklist ( u ) ;
addWorklist ( v ) ;
return ;
}
bool u_is_colored = precolored . count ( u ) | | coloredNodes . count ( u ) ;
bool v_is_colored = precolored . count ( v ) | | coloredNodes . count ( v ) ;
if ( u_is_colored & & v_is_colored ) {
PhysicalReg u_color = precolored . count ( u )
? static_cast < PhysicalReg > ( u - static_cast < unsigned > ( PhysicalReg : : PHYS_REG_START_ID ) )
: color_map . at ( u ) ;
PhysicalReg v_color = precolored . count ( v )
? static_cast < PhysicalReg > ( v - static_cast < unsigned > ( PhysicalReg : : PHYS_REG_START_ID ) )
: color_map . at ( v ) ;
if ( u_color ! = v_color ) {
if ( DEEPERDEBUG ) std : : cerr < < " -> Constrained (move between two different precolored nodes: "
< < regToString ( u_color ) < < " and " < < regToString ( v_color ) < < " ). \n " ;
constrainedMoves . insert ( move ) ;
return ;
} else {
if ( DEEPERDEBUG ) std : : cerr < < " -> Trivial coalesce (move between same precolored nodes). \n " ;
coalescedMoves . insert ( move ) ;
combine ( u , v ) ;
addWorklist ( u ) ;
return ;
}
}
// 类型检查
if ( isFPVReg ( u ) ! = isFPVReg ( v ) ) {
if ( DEEPERDEBUG ) std : : cerr < < " -> Constrained (type mismatch: " < < regIdToString ( u ) < < " is "
< < ( isFPVReg ( u ) ? " float " : " int " ) < < " , " < < regIdToString ( v ) < < " is "
@ -539,25 +667,11 @@ void RISCv64RegAlloc::coalesce() {
return ;
}
// 注意: 如果v已经是u的邻居, pre_interfere 会为true。
// 但如果v不在adjList中( 例如v是预着色节点) , 我们需要检查u是否在v的邻居中。
// 为了简化, 我们假设adjList包含了所有虚拟寄存器。对于(Phys, Virt)对, 冲突信息存储在Virt节点的邻接表中。
bool pre_interfere = ( adjList . count ( v ) & & adjList . at ( v ) . count ( u ) ) | | ( adjList . count ( u ) & & adjList . at ( u ) . count ( v ) ) ;
if ( pre_interfere ) {
if ( DEEPERDEBUG ) std : : cerr < < " -> Constrained (nodes already interfere). \n " ;
constrainedMoves . insert ( move ) ;
addWorklist ( u ) ;
addWorklist ( v ) ;
return ;
}
// 考虑物理寄存器和已预着色的虚拟寄存器
// 启发式判断逻辑
bool u_is_effectively_precolored = precolored . count ( u ) | | coloredNodes . count ( u ) ;
bool can_coalesce = false ;
if ( u_is_effectively_precolored ) {
// --- 场景1: u是物理寄存器或已预着色虚拟寄存器, 使用 George 启发式 ---
if ( DEEPERDEBUG ) std : : cerr < < " -> Trying George Heuristic (u is effectively precolored)... \n " ;
VRegSet neighbors_of_v = adjacent ( v ) ;
@ -1227,11 +1341,7 @@ bool RISCv64RegAlloc::georgeHeuristic(unsigned t, unsigned u) {
int K = isFPVReg ( t ) ? K_fp : K_int ;
// 缺陷 #2 修正: 移除了致命的 || precolored.count(u) 条件。
// 在此函数的上下文中, u 总是预着色的物理寄存器ID, 导致旧的条件永远为true, 使整个启发式失效。
// 正确的逻辑是检查: 邻居t的度数是否小于K, 或者t是否已经与u冲突。
// return degree.at(t) < K || adjList.at(t).count(u);
return degree . at ( t ) < K | | ! adjList . at ( t ) . count ( u ) ;
return degree . at ( t ) < K | | adjList . at ( t ) . count ( u ) ;
}
void RISCv64RegAlloc : : combine ( unsigned u , unsigned v ) {