@@ -1,27 +1,82 @@
# include "RISCv64LinearScan.h"
# include "RISCv64LLIR.h"
# include "RISCv64ISel.h"
# include "RISCv64Info.h"
# include <iostream>
# include <algorithm>
# include <set>
# include <sstream>
# include <functional>
// 外部调试级别控制变量
extern int DEBUG ;
extern int DEEPDEBUG ;
extern int DEEPERDEBUG ;
namespace sysy {
// --- 调试辅助函数 ---
std : : string pregToString ( PhysicalReg preg ) {
static const std : : map < PhysicalReg , std : : string > preg_names = {
{ PhysicalReg : : ZERO , " zero " } , { PhysicalReg : : RA , " ra " } , { PhysicalReg : : SP , " sp " } , { PhysicalReg : : GP , " gp " } , { PhysicalReg : : TP , " tp " } ,
{ PhysicalReg : : T0 , " t0 " } , { PhysicalReg : : T1 , " t1 " } , { PhysicalReg : : T2 , " t2 " } , { PhysicalReg : : T3 , " t3 " } , { PhysicalReg : : T4 , " t4 " } , { PhysicalReg : : T5 , " t5 " } , { PhysicalReg : : T6 , " t6 " } ,
{ PhysicalReg : : S0 , " s0 " } , { PhysicalReg : : S1 , " s1 " } , { PhysicalReg : : S2 , " s2 " } , { PhysicalReg : : S3 , " s3 " } , { PhysicalReg : : S4 , " s4 " } , { PhysicalReg : : S5 , " s5 " } , { PhysicalReg : : S6 , " s6 " } , { PhysicalReg : : S7 , " s7 " } , { PhysicalReg : : S8 , " s8 " } , { PhysicalReg : : S9 , " s9 " } , { PhysicalReg : : S10 , " s10 " } , { PhysicalReg : : S11 , " s11 " } ,
{ PhysicalReg : : A0 , " a0 " } , { PhysicalReg : : A1 , " a1 " } , { PhysicalReg : : A2 , " a2 " } , { PhysicalReg : : A3 , " a3 " } , { PhysicalReg : : A4 , " a4 " } , { PhysicalReg : : A5 , " a5 " } , { PhysicalReg : : A6 , " a6 " } , { PhysicalReg : : A7 , " a7 " } ,
{ PhysicalReg : : F0 , " f0 " } , { PhysicalReg : : F1 , " f1 " } , { PhysicalReg : : F2 , " f2 " } , { PhysicalReg : : F3 , " f3 " } , { PhysicalReg : : F4 , " f4 " } , { PhysicalReg : : F5 , " f5 " } , { PhysicalReg : : F6 , " f6 " } , { PhysicalReg : : F7 , " f7 " } ,
{ PhysicalReg : : F8 , " f8 " } , { PhysicalReg : : F9 , " f9 " } , { PhysicalReg : : F10 , " f10 " } , { PhysicalReg : : F11 , " f11 " } , { PhysicalReg : : F12 , " f12 " } , { PhysicalReg : : F13 , " f13 " } , { PhysicalReg : : F14 , " f14 " } , { PhysicalReg : : F15 , " f15 " } ,
{ PhysicalReg : : F16 , " f16 " } , { PhysicalReg : : F17 , " f17 " } , { PhysicalReg : : F18 , " f18 " } , { PhysicalReg : : F19 , " f19 " } , { PhysicalReg : : F20 , " f20 " } , { PhysicalReg : : F21 , " f21 " } , { PhysicalReg : : F22 , " f22 " } , { PhysicalReg : : F23 , " f23 " } ,
{ PhysicalReg : : F24 , " f24 " } , { PhysicalReg : : F25 , " f25 " } , { PhysicalReg : : F26 , " f26 " } , { PhysicalReg : : F27 , " f27 " } , { PhysicalReg : : F28 , " f28 " } , { PhysicalReg : : F29 , " f29 " } , { PhysicalReg : : F30 , " f30 " } , { PhysicalReg : : F31 , " f31 " } ,
{ PhysicalReg : : INVALID , " INVALID " }
} ;
if ( preg_names . count ( preg ) ) return preg_names . at ( preg ) ;
return " UnknownPreg " ;
}
template < typename T >
std : : string setToString ( const std : : set < T > & s , std : : function < std : : string ( T ) > formatter ) {
std : : stringstream ss ;
ss < < " { " ;
for ( auto it = s . begin ( ) ; it ! = s . end ( ) ; + + it ) {
ss < < formatter ( * it ) < < ( std : : next ( it ) = = s . end ( ) ? " " : " , " ) ;
}
ss < < " } " ;
return ss . str ( ) ;
}
std : : string vregSetToString ( const std : : set < unsigned > & s ) {
return setToString < unsigned > ( s , [ ] ( unsigned v ) { return " %v " + std : : to_string ( v ) ; } ) ;
}
std : : string pregSetToString ( const std : : set < PhysicalReg > & s ) {
return setToString < PhysicalReg > ( s , pregToString ) ;
}
std : : string opcodeToString ( RVOpcodes opcode ) {
static const std : : map < RVOpcodes , std : : string > opcode_names = {
{ RVOpcodes : : ADD , " add " } , { RVOpcodes : : ADDI , " addi " } , { RVOpcodes : : ADDW , " addw " } , { RVOpcodes : : ADDIW , " addiw " } ,
{ RVOpcodes : : SUB , " sub " } , { RVOpcodes : : SUBW , " subw " } , { RVOpcodes : : MUL , " mul " } , { RVOpcodes : : MULW , " mulw " } ,
{ RVOpcodes : : DIV , " div " } , { RVOpcodes : : DIVW , " divw " } , { RVOpcodes : : REM , " rem " } , { RVOpcodes : : REMW , " remw " } ,
{ RVOpcodes : : SLT , " slt " } , { RVOpcodes : : LW , " lw " } , { RVOpcodes : : LD , " ld " } , { RVOpcodes : : SW , " sw " } , { RVOpcodes : : SD , " sd " } ,
{ RVOpcodes : : FLW , " flw " } , { RVOpcodes : : FSW , " fsw " } , { RVOpcodes : : CALL , " call " } , { RVOpcodes : : RET , " ret " } ,
{ RVOpcodes : : MV , " mv " } , { RVOpcodes : : LI , " li " } , { RVOpcodes : : LA , " la " } , { RVOpcodes : : BNE , " bne " } ,
{ RVOpcodes : : J , " j " } , { RVOpcodes : : LABEL , " label " }
} ;
if ( opcode_names . count ( opcode ) ) return opcode_names . at ( opcode ) ;
return " Op( " + std : : to_string ( static_cast < int > ( opcode ) ) + " ) " ;
}
RISCv64LinearScan : : RISCv64LinearScan ( MachineFunction * mfunc )
: MFunc ( mfunc ) ,
ISel ( mfunc - > getISel ( ) ) ,
vreg_type_map ( ISel - > getVRegTypeMap ( ) ) {
// 初始化可用的物理寄存器池,与图着色版本保持一致
// 整数寄存器
allocable_int_regs = {
PhysicalReg : : T0 , PhysicalReg : : T1 , PhysicalReg : : T2 , PhysicalReg : : T3 , PhysicalReg : : T4 , /*T5保留作为大立即数加载寄存器*/ PhysicalReg : : T6 ,
PhysicalReg : : T0 , PhysicalReg : : T1 , PhysicalReg : : T2 , PhysicalReg : : T3 , PhysicalReg : : T4 , PhysicalReg : : T6 ,
PhysicalReg : : A0 , PhysicalReg : : A1 , PhysicalReg : : A2 , PhysicalReg : : A3 , PhysicalReg : : A4 , PhysicalReg : : A5 , PhysicalReg : : A6 , PhysicalReg : : A7 ,
PhysicalReg : : S1 , PhysicalReg : : S2 , PhysicalReg : : S3 , PhysicalReg : : S4 , PhysicalReg : : S5 , PhysicalReg : : S6 , PhysicalReg : : S7 ,
PhysicalReg : : S8 , PhysicalReg : : S9 , PhysicalReg : : S10 , PhysicalReg : : S11 ,
} ;
// 浮点寄存器
allocable_fp_regs = {
PhysicalReg : : F0 , PhysicalReg : : F1 , PhysicalReg : : F2 , PhysicalReg : : F3 , PhysicalReg : : F4 , PhysicalReg : : F5 , PhysicalReg : : F6 , PhysicalReg : : F7 ,
PhysicalReg : : F10 , PhysicalReg : : F11 , PhysicalReg : : F12 , PhysicalReg : : F13 , PhysicalReg : : F14 , PhysicalReg : : F15 , PhysicalReg : : F16 , PhysicalReg : : F17 ,
@@ -29,24 +84,20 @@ RISCv64LinearScan::RISCv64LinearScan(MachineFunction* mfunc)
PhysicalReg : : F23 , PhysicalReg : : F24 , PhysicalReg : : F25 , PhysicalReg : : F26 , PhysicalReg : : F27 ,
PhysicalReg : : F28 , PhysicalReg : : F29 , PhysicalReg : : F30 , PhysicalReg : : F31 ,
} ;
// 新增: 识别所有通过寄存器传递的参数, 并建立vreg到物理寄存器(preg)的映射
// 这等同于图着色算法中的“预着色”步骤。
if ( MFunc - > getFunc ( ) ) {
int int_arg_idx = 0 ;
int fp_arg_idx = 0 ;
for ( Argument * arg : MFunc - > getFunc ( ) - > getArguments ( ) ) {
unsigned arg_vreg = ISel - > getVReg ( arg ) ;
if ( arg - > getType ( ) - > isFloat ( ) ) {
if ( fp_arg_idx < 8 ) { // fa0-fa7
auto preg = static_cast < PhysicalReg > ( static_cast < int > ( PhysicalReg : : F10 ) + fp_arg_idx ) ;
if ( fp_arg_idx < 8 ) {
auto preg = static_cast < PhysicalReg > ( static_cast < int > ( PhysicalReg : : F10 ) + fp_arg_idx + + ) ;
abi_vreg_map [ arg_vreg ] = preg ;
fp_arg_idx + + ;
}
} else { // 整数或指针
if ( int_arg_idx < 8 ) { // a0-a7
auto preg = static_cast < PhysicalReg > ( static_cast < int > ( PhysicalReg : : A0 ) + int_arg_idx ) ;
} else {
if ( int_arg_idx < 8 ) {
auto preg = static_cast < PhysicalReg > ( static_cast < int > ( PhysicalReg : : A0 ) + int_arg_idx + + ) ;
abi_vreg_map [ arg_vreg ] = preg ;
int_arg_idx + + ;
}
}
}
@@ -54,34 +105,33 @@ RISCv64LinearScan::RISCv64LinearScan(MachineFunction* mfunc)
}
void RISCv64LinearScan : : run ( ) {
if ( DEBUG ) std : : cerr < < " ===== Running Linear Scan Register Allocation for function: " < < MFunc - > getName ( ) < < " ===== \n " ;
if ( DEBUG ) std : : cerr < < " ===== [LSRA] Running for function: " < < MFunc - > getName ( ) < < " ===== \n " ;
bool changed = true ;
int iteration = 1 ;
while ( changed ) {
// 1. 准备阶段
if ( DEBUG & & iteration > 1 ) {
std : : cerr < < " \n ----- [LSRA] Re-running iteration " < < iteration < < " ----- \n " ;
}
linearizeBlocks ( ) ;
computeLiveIntervals ( ) ;
// 2. 执行线性扫描
changed = linearScan ( ) ;
// 3. 如果有溢出,重写代码,然后下一轮重新开始
if ( changed ) {
if ( DEBUG ) std : : cerr < < " [LSRA] Spilling detected, will rewrite program. \n " ;
rewriteProgram ( ) ;
if ( DEBUG ) std : : cerr < < " --- Spilling detected, re-running linear scan --- \n " ;
}
iteration + + ;
}
// 4. 将最终分配结果应用到机器指令
if ( DEBUG ) std : : cerr < < " [LSRA] Applying final allocation. \n " ;
applyAllocation ( ) ;
// 5. 收集用到的被调用者保存寄存器
MFunc - > getFrameInfo ( ) . vreg_to_preg_map = this - > vreg_to_preg_map ;
collectUsedCalleeSavedRegs ( ) ;
if ( DEBUG ) std : : cerr < < " ===== Finished Linear Scan Register Allocation ===== \n \n " ;
if ( DEBUG ) std : : cerr < < " ===== [LSRA] Finished for function: " < < MFunc - > getName ( ) < < " ===== \n \n " ;
}
// 步骤 1.1: 对基本块进行线性化,这里我们简单地按现有顺序排列
void RISCv64LinearScan : : linearizeBlocks ( ) {
linear_order_blocks . clear ( ) ;
for ( auto & mbb : MFunc - > getBlocks ( ) ) {
@@ -89,14 +139,14 @@ void RISCv64LinearScan::linearizeBlocks() {
}
}
// RISCv64LinearScan.cpp
// 步骤 1.2: 计算活跃区间 (最终修复版)
void RISCv64LinearScan : : computeLiveIntervals ( ) {
if ( DEBUG ) std : : cerr < < " [LSRA-Live] Starting live interval computation. \n " ;
instr_numbering . clear ( ) ;
live_intervals . clear ( ) ;
unhandled . clear ( ) ;
// a. 对所有指令进行线性编号, 并记录CALL指令的位置
// a. 对所有指令进行线性编号
int num = 0 ;
std : : set < int > call_locations ;
for ( auto * mbb : linear_order_blocks ) {
@@ -105,88 +155,143 @@ void RISCv64LinearScan::computeLiveIntervals() {
if ( instr - > getOpcode ( ) = = RVOpcodes : : CALL ) {
call_locations . insert ( num ) ;
}
num + = 2 ; // 指令编号间隔为2, 方便在溢出重写时插入指令
num + = 2 ;
}
}
// b. 遍历所有指令, 记录每个vreg首次和末次出现的位置
std : : map < unsigned , std : : pai r< int , int > > vreg_ranges ; // vreg -> {first_instr_num, last_instr_num}
// b. 活跃变量分析(数据流分析部分)
if ( DEEPDEBUG ) std : : cer r < < " [Live] Starting live variable dataflow analysis... \n " ;
std : : map < const MachineBasicBlock * , std : : set < unsigned > > live_in , live_out ;
bool changed = true ;
int df_iter = 0 ;
while ( changed ) {
changed = false ;
df_iter + + ;
std : : vector < MachineBasicBlock * > reversed_blocks = linear_order_blocks ;
std : : reverse ( reversed_blocks . begin ( ) , reversed_blocks . end ( ) ) ;
for ( auto * mbb : reversed_blocks ) {
std : : set < unsigned > current_live_out ;
for ( auto * succ : mbb - > successors ) {
current_live_out . insert ( live_in [ succ ] . begin ( ) , live_in [ succ ] . end ( ) ) ;
}
for ( auto * mbb : linear_order_blocks ) {
for ( auto & instr_ptr : mbb - > getInstructions ( ) ) {
const MachineInstr * instr = instr_ptr . get ( ) ;
int instr_num = instr_numbering . at ( instr ) ;
std : : set < unsigned > use , def ;
getInstrUseDef ( instr , use , def ) ;
std : : set < unsigned > temp_live = current_live_out ;
auto all_vregs = use ;
all_vregs . insert ( def . begin ( ) , def . end ( ) ) ;
for ( unsigned vreg : all_vregs ) {
i f ( vreg_ranges . find ( vreg ) = = vreg_ranges . end ( ) ) {
vreg_ranges [ vreg ] = { instr_num , instr_num } ;
} else {
vreg_ranges [ vreg ] . second = std : : max ( vreg_ranges [ vreg ] . second , instr_num ) ;
}
auto & instrs = mbb - > getInstructions ( ) ;
for ( auto it = instrs . r begin( ) ; it ! = instrs . r end( ) ; + + it ) {
use . clear ( ) ; def . clear ( ) ;
getInstrUseDef ( it - > get ( ) , use , def ) ;
for ( unsigned vreg : def ) temp_live . erase ( vreg ) ;
for ( unsigned vreg : use ) temp_live . insert ( vreg ) ;
}
if ( live_in [ mbb ] ! = temp_live | | live_out [ mbb ] ! = current_live_out ) {
changed = true ;
live_in [ mbb ] = temp_live ;
live_out [ mbb ] = current_live_out ;
}
}
}
if ( DEEPDEBUG ) std : : cerr < < " [Live] Dataflow analysis converged after " < < df_iter < < " iterations. \n " ;
// c. 根据记录的边界, 创建LiveInterval对象, 并检查是否跨越CALL
for ( auto con st& [ vreg , range ] : vreg_ranges ) {
// c. 根据指令遍历和活跃出口信息,精确构建区间
i f ( DEEPDEBUG ) std : : cerr < < " [Live] Building precise intervals... \n " ;
std : : map < unsigned , int > first_occurrence , last_occurrence ;
for ( auto * mbb : linear_order_blocks ) {
for ( auto & instr_ptr : mbb - > getInstructions ( ) ) {
int instr_num = instr_numbering . at ( instr_ptr . get ( ) ) ;
std : : set < unsigned > use , def ;
getInstrUseDef ( instr_ptr . get ( ) , use , def ) ;
std : : set < unsigned > all_vregs = use ;
all_vregs . insert ( def . begin ( ) , def . end ( ) ) ;
for ( unsigned vreg : all_vregs ) {
if ( first_occurrence . find ( vreg ) = = first_occurrence . end ( ) ) {
first_occurrence [ vreg ] = instr_num ;
}
last_occurrence [ vreg ] = instr_num ;
}
}
}
// 使用 live_out 信息修正区间的结束点
for ( auto const & [ mbb , live_set ] : live_out ) {
if ( mbb - > getInstructions ( ) . empty ( ) ) continue ;
int block_end_num = instr_numbering . at ( mbb - > getInstructions ( ) . back ( ) . get ( ) ) ;
for ( unsigned vreg : live_set ) {
if ( last_occurrence . count ( vreg ) ) {
last_occurrence [ vreg ] = std : : max ( last_occurrence [ vreg ] , block_end_num ) ;
}
}
}
// 创建最终的 LiveInterval 对象
for ( auto const & [ vreg , start ] : first_occurrence ) {
live_intervals . emplace ( vreg , LiveInterval ( vreg ) ) ;
auto & interval = live_intervals . at ( vreg ) ;
interval . start = range . firs t;
interval . end = range . second ;
interval . start = star t;
interval . end = last_occurrence . at ( vreg ) ;
// 检查此区间是否跨越了任何CALL指令
auto it = call_locations . lower_bound ( interval . start ) ;
if ( it ! = call_locations . end ( ) & & * it < interval . end ) {
interval . crosses_call = true ;
}
}
// d. 将所有计算出的活跃区间放入 unhandled 列表
// d. 排序并准备分配
for ( auto & pair : live_intervals ) {
unhandled . push_back ( & pair . second ) ;
}
std : : sort ( unhandled . begin ( ) , unhandled . end ( ) , [ ] ( const LiveInterval * a , const LiveInterval * b ) {
return a - > start < b - > start ;
} ) ;
if ( DEBUG ) {
std : : cerr < < " [LSRA-Live] Finished. Total intervals: " < < unhandled . size ( ) < < " \n " ;
if ( DEEPDEBUG ) {
std : : cerr < < " [Live] Computed Intervals (vreg: [start, end]): \n " ;
for ( const auto * interval : unhandled ) {
std : : cerr < < " %v " < < interval - > vreg < < " : [ " < < interval - > start < < " , " < < interval - > end < < " ] "
< < ( interval - > crosses_call ? " (crosses call) " : " " ) < < " \n " ;
}
}
}
}
// RISCv64LinearScan.cpp
// 在类的定义中添加一个辅助函数来判断寄存器类型
bool isCalleeSaved ( PhysicalReg preg ) {
if ( preg > = PhysicalReg : : S1 & & preg < = PhysicalReg : : S11 ) return true ;
if ( preg = = PhysicalReg : : S0 ) return true ; // s0 通常也作为被调用者保存
// 浮点寄存器
if ( preg = = PhysicalReg : : S0 ) return true ;
if ( preg > = PhysicalReg : : F8 & & preg < = PhysicalReg : : F9 ) return true ;
if ( preg > = PhysicalReg : : F18 & & preg < = PhysicalReg : : F27 ) return true ;
return false ;
}
// 线性扫描主算法
bool RISCv64LinearScan : : linearScan ( ) {
if ( DEBUG ) std : : cerr < < " [LSRA-Scan] Starting main linear scan algorithm. \n " ;
active . clear ( ) ;
spilled_vregs . clear ( ) ;
vreg_to_preg_map . clear ( ) ;
// 将寄存器池分为调用者保存和被调用者保存两类
std : : set < PhysicalReg > free_caller_int_regs , free_callee_int_regs ;
std : : set < PhysicalReg > free_caller_fp_regs , free_callee_fp_regs ;
for ( auto preg : allocable_int_regs ) {
if ( isCalleeSaved ( preg ) ) free_callee_int_regs . insert ( preg ) ;
else free_caller_int_regs . insert ( preg ) ;
if ( isCalleeSaved ( preg ) ) free_callee_int_regs . insert ( preg ) ; else free_caller_int_regs . insert ( preg ) ;
}
for ( auto preg : allocable_fp_regs ) {
if ( isCalleeSaved ( preg ) ) free_callee_fp_regs . insert ( preg ) ;
else free_caller_fp_regs . insert ( preg ) ;
if ( isCalleeSaved ( preg ) ) free_callee_fp_regs . insert ( preg ) ; else free_caller_fp_regs . insert ( preg ) ;
}
if ( DEEPDEBUG ) {
std : : cerr < < " [Scan] Initial free regs: \n " ;
std : : cerr < < " Caller-Saved Int: " < < pregSetToString ( free_caller_int_regs ) < < " \n " ;
std : : cerr < < " Callee-Saved Int: " < < pregSetToString ( free_callee_int_regs ) < < " \n " ;
}
// 预处理ABI参数寄存器
vreg_to_preg_map . insert ( abi_vreg_map . begin ( ) , abi_vreg_map . end ( ) ) ;
std : : vector < LiveInterval * > normal_unhandled ;
for ( LiveInterval * interval : unhandled ) {
@@ -205,13 +310,14 @@ bool RISCv64LinearScan::linearScan() {
unhandled = normal_unhandled ;
std : : sort ( active . begin ( ) , active . end ( ) , [ ] ( const LiveInterval * a , const LiveInterval * b ) { return a - > end < b - > end ; } ) ;
// 主循环
for ( LiveInterval * current : unhandled ) {
// a. 释放active列表中已结束的区间
if ( DEEPDEBUG ) std : : cerr < < " \n [Scan] Processing interval %v " < < current - > vreg < < " [ " < < current - > start < < " , " < < current - > end < < " ] \n " ;
std : : vector < LiveInterval * > new_active ;
for ( LiveInterval * active_interval : active ) {
if ( active_interval - > end < current - > start ) {
PhysicalReg preg = vreg_to_preg_map . at ( active_interval - > vreg ) ;
if ( DEEPDEBUG ) std : : cerr < < " [Scan] Expiring interval %v " < < active_interval - > vreg < < " , freeing " < < pregToString ( preg ) < < " \n " ;
if ( isFPVReg ( active_interval - > vreg ) ) {
if ( isCalleeSaved ( preg ) ) free_callee_fp_regs . insert ( preg ) ; else free_caller_fp_regs . insert ( preg ) ;
} else {
@@ -223,21 +329,17 @@ bool RISCv64LinearScan::linearScan() {
}
active = new_active ;
// b. 约束化地为当前区间分配寄存器
bool is_fp = isFPVReg ( current - > vreg ) ;
auto & free_caller = is_fp ? free_caller_fp_regs : free_caller_int_regs ;
auto & free_callee = is_fp ? free_callee_fp_regs : free_callee_int_regs ;
PhysicalReg allocated_preg = PhysicalReg : : INVALID ;
if ( current - > crosses_call ) {
// 跨调用区间:必须使用被调用者保存寄存器
if ( ! free_callee . empty ( ) ) {
allocated_preg = * free_callee . begin ( ) ;
free_callee . erase ( allocated_preg ) ;
}
} else {
// 非跨调用区间:优先使用调用者保存寄存器
if ( ! free_caller . empty ( ) ) {
allocated_preg = * free_caller . begin ( ) ;
free_caller . erase ( allocated_preg ) ;
@@ -248,75 +350,73 @@ bool RISCv64LinearScan::linearScan() {
}
if ( allocated_preg ! = PhysicalReg : : INVALID ) {
if ( DEEPDEBUG ) std : : cerr < < " [Scan] Allocated " < < pregToString ( allocated_preg ) < < " to %v " < < current - > vreg < < " \n " ;
vreg_to_preg_map [ current - > vreg ] = allocated_preg ;
active . push_back ( current ) ;
std : : sort ( active . begin ( ) , active . end ( ) , [ ] ( const LiveInterval * a , const LiveInterval * b ) { return a - > end < b - > end ; } ) ;
} else {
// c. 没有可用寄存器,需要溢出
if ( DEEPDEBUG ) std : : cerr < < " [Scan] No free registers for %v " < < current - > vreg < < " . Spilling... \n " ;
spillAtInterval ( current ) ;
}
}
return ! spilled_vregs . empty ( ) ;
}
void RISCv64LinearScan : : chooseRegForInterval ( LiveInterval * current ) {
bool is_fp = isFPVReg ( current - > vreg ) ;
auto & free_regs = is_fp ? free_fp_regs : free_int_regs ;
if ( ! free_regs . empty ( ) ) {
// 有可用寄存器
PhysicalReg preg = * free_regs . begin ( ) ;
free_regs . erase ( free_regs . begin ( ) ) ;
vreg_to_preg_map [ current - > vreg ] = preg ;
active . push_back ( current ) ;
// 保持 active 列表按结束点排序
std : : sort ( active . begin ( ) , active . end ( ) , [ ] ( const LiveInterval * a , const LiveInterval * b ) {
return a - > end < b - > end ;
} ) ;
} else {
// 没有可用寄存器,需要溢出
spillAtInterval ( current ) ;
}
}
void RISCv64LinearScan : : spillAtInterval ( LiveInterval * current ) {
LiveInterval * spill_candidate = nullptr ;
// 启发式溢出:
// 如果current需要callee-saved, 则从active中找一个占用callee-saved且结束最晚的区间比较
// 否则, 找active中结束最晚的区间
// 这里简化处理: 总是找active中结束最晚的区间
auto last_active = active . back ( ) ;
if ( ! active . empty ( ) ) {
spill_candidate = active . back ( ) ;
}
if ( last_activ e- > end > current - > end ) {
// 溢出active中的区间
spill_candidate = last_active ;
if ( spill_candidate & & spill_candidat e- > end > current - > end ) {
if ( DEEPDEBUG ) std : : cerr < < " [Spill] Current interval ends at " < < current - > end < < " , active interval %v " < < spill_candidate - > vreg < < " ends at " < < spill_candidate - > end < < " . Spilling active. \n " ;
PhysicalReg preg = vreg_to_preg_map . at ( spill_candidate - > vreg ) ;
vreg_to_preg_map [ current - > vreg ] = preg ; // 把换出的寄存器给current
// 更新active列表
vreg_to_preg_map [ current - > vreg ] = preg ;
active . pop_back ( ) ;
active . push_back ( current ) ;
std : : sort ( active . begin ( ) , active . end ( ) , [ ] ( const LiveInterval * a , const LiveInterval * b ) { return a - > end < b - > end ; } ) ;
spilled_vregs . insert ( spill_candidate - > vreg ) ;
} else {
// 溢出当前区间
if ( DEEPDEBUG ) std : : cerr < < " [Spill] Current interval %v " < < current - > vreg < < " ends at " < < current - > end < < " which is later than all active intervals. Spilling current. \n " ;
spilled_vregs . insert ( current - > vreg ) ;
}
}
// 步骤 3: 重写程序,插入溢出代码
void RISCv64LinearScan : : rewriteProgram ( ) {
if ( DEBUG ) {
std : : cerr < < " [LSRA-Rewrite] Starting program rewrite. Spilled vregs: " < < vregSetToString ( spilled_vregs ) < < " \n " ;
}
StackFrameInfo & frame_info = MFunc - > getFrameInfo ( ) ;
int spill_offset = frame_info . locals_size ; // 溢出区域接在局部变量之后
// 遵循后端流水线设计,在本地变量区域之下为溢出变量分配空间。
// locals_end_offset 是由 EliminateFrameIndices Pass 计算好的局部变量区域的下边界。
// 我们在此基础上,减去已有的溢出区大小,作为新溢出槽的起始点。
int spill_current_offset = frame_info . locals_end_offset - frame_info . spill_size ;
for ( unsigned vreg : spilled_vregs ) {
if ( frame_info . spill_offsets . count ( vreg ) ) continue ; // 避免重复分配
// 只为本轮新发现的溢出变量分配空间
if ( frame_info . spill_offsets . count ( vreg ) ) continue ;
int size = isFPVReg ( vreg ) ? 4 : ( vreg_type_map . at ( vreg ) - > isPointer ( ) ? 8 : 4 ) ;
spill_offset + = size ;
spill_offset = ( spill_offset + 7 ) & ~ 7 ; // 8字节对齐
frame_info . spill_offsets [ vreg ] = - ( 16 + spill_offset ) ;
Type * type = vreg_type_map . count ( vreg ) ? vreg_type_map . at ( vreg ) : Type : : getIntType ( ) ;
int size = isFPVReg ( vreg ) ? 4 : ( type - > isPointer ( ) ? 8 : 4 ) ;
// 在当前偏移基础上继续向下(地址变得更负)分配空间
spill_current_offset - = size ;
// 对齐新的、更小的地址, RISC-V 要求8字节对齐
spill_current_offset = ( spill_current_offset & ~ 7 ) ;
// 将计算出的、不会冲突的正确偏移量存入 spill_offsets
frame_info . spill_offsets [ vreg ] = spill_current_offset ;
if ( DEEPDEBUG ) std : : cerr < < " [Rewrite] Assigned stack offset " < < frame_info . spill_offsets . at ( vreg ) < < " to spilled %v " < < vreg < < " \n " ;
}
frame_info . spill_size = spill_offset - frame_info . locals_size ;
// 更新总的溢出区域大小。
// spill_size = -(结束偏移 - 开始偏移)
// 注意: locals_end_offset 和 spill_current_offset 都是负数。
frame_info . spill_size = - ( spill_current_offset - frame_info . locals_end_offset ) ;
for ( auto & mbb : MFunc - > getBlocks ( ) ) {
auto & instrs = mbb - > getInstructions ( ) ;
@@ -327,11 +427,10 @@ void RISCv64LinearScan::rewriteProgram() {
std : : set < unsigned > use_vregs , def_vregs ;
getInstrUseDef ( instr . get ( ) , use_vregs , def_vregs ) ;
// 建立溢出vreg到新临时vreg的映射
std : : map < unsigned , unsigned > use_remap ;
std : : map < unsigned , unsigned > def_remap ;
// 1. 为所有溢出的USE创建LOAD指令和映射
// 为每个溢出的 use 操作数创建新vreg并插入 load
for ( unsigned old_vreg : use_vregs ) {
if ( spilled_vregs . count ( old_vreg ) & & use_remap . find ( old_vreg ) = = use_remap . end ( ) ) {
Type * type = vreg_type_map . at ( old_vreg ) ;
@@ -345,11 +444,12 @@ void RISCv64LinearScan::rewriteProgram() {
std : : make_unique < RegOperand > ( PhysicalReg : : S0 ) ,
std : : make_unique < ImmOperand > ( frame_info . spill_offsets . at ( old_vreg ) )
) ) ;
if ( DEEPDEBUG ) std : : cerr < < " [Rewrite] Inserting LOAD for use of %v " < < old_vreg < < " into new %v " < < new_temp_vreg < < " \n " ;
new_instrs . push_back ( std : : move ( load ) ) ;
}
}
// 2. 为所有溢出的DEF创建映射
// 为每个溢出的 def 操作数创建新vreg
for ( unsigned old_vreg : def_vregs ) {
if ( spilled_vregs . count ( old_vreg ) & & def_remap . find ( old_vreg ) = = def_remap . end ( ) ) {
Type * type = vreg_type_map . at ( old_vreg ) ;
@@ -358,10 +458,8 @@ void RISCv64LinearScan::rewriteProgram() {
}
}
// 3. 基于角色精确地替换原指令中的操作数
auto opcode = instr - > getOpcode ( ) ;
auto & operands = instr - > getOperands ( ) ;
auto replace_reg_op = [ ] ( RegOperand * reg_op , const std : : map < unsigned , unsigned > & remap ) {
if ( reg_op - > isVirtual ( ) & & remap . count ( reg_op - > getVRegNum ( ) ) ) {
reg_op - > setVRegNum ( remap . at ( reg_op - > getVRegNum ( ) ) ) ;
@@ -370,13 +468,11 @@ void RISCv64LinearScan::rewriteProgram() {
if ( op_info . count ( opcode ) ) {
const auto & info = op_info . at ( opcode ) ;
// 替换 Defs
for ( int idx : info . first ) {
if ( idx < operands . size ( ) & & operands [ idx ] - > getKind ( ) = = MachineOperand : : KIND_REG ) {
replace_reg_op ( static_cast < RegOperand * > ( operands [ idx ] . get ( ) ) , def_remap ) ;
}
}
// 替换 Uses
for ( int idx : info . second ) {
if ( idx < operands . size ( ) ) {
if ( operands [ idx ] - > getKind ( ) = = MachineOperand : : KIND_REG ) {
@@ -387,7 +483,6 @@ void RISCv64LinearScan::rewriteProgram() {
}
}
} else if ( opcode = = RVOpcodes : : CALL ) {
// 特殊处理 CALL 指令
if ( ! operands . empty ( ) & & operands [ 0 ] - > getKind ( ) = = MachineOperand : : KIND_REG ) {
replace_reg_op ( static_cast < RegOperand * > ( operands [ 0 ] . get ( ) ) , def_remap ) ;
}
@@ -398,10 +493,9 @@ void RISCv64LinearScan::rewriteProgram() {
}
}
// 4. 将修改后的指令放入新列表
new_instrs . push_back ( std : : move ( instr ) ) ;
// 5. 为所有溢出的DEF创建STORE 指令
// 为每个溢出的 def 操作数,在原指令后插入 store 指令
for ( const auto & pair : def_remap ) {
unsigned old_vreg = pair . first ;
unsigned new_temp_vreg = pair . second ;
@@ -413,6 +507,7 @@ void RISCv64LinearScan::rewriteProgram() {
std : : make_unique < RegOperand > ( PhysicalReg : : S0 ) ,
std : : make_unique < ImmOperand > ( frame_info . spill_offsets . at ( old_vreg ) )
) ) ;
if ( DEEPDEBUG ) std : : cerr < < " [Rewrite] Inserting STORE for def of %v " < < old_vreg < < " from new %v " < < new_temp_vreg < < " \n " ;
new_instrs . push_back ( std : : move ( store ) ) ;
}
}
@@ -420,24 +515,25 @@ void RISCv64LinearScan::rewriteProgram() {
}
}
// 步骤 4: 应用最终分配结果
void RISCv64LinearScan : : applyAllocation ( ) {
if ( DEBUG ) std : : cerr < < " [LSRA-Apply] Applying final vreg->preg mapping. \n " ;
for ( auto & mbb : MFunc - > getBlocks ( ) ) {
if ( DEEPDEBUG ) std : : cerr < < " [Apply] In block " < < mbb - > getName ( ) < < " : \n " ;
for ( auto & instr_ptr : mbb - > getInstructions ( ) ) {
if ( DEEPERDEBUG ) std : : cerr < < " [Apply] Instr " < < opcodeToString ( instr_ptr - > getOpcode ( ) ) < < " : " ;
for ( auto & op_ptr : instr_ptr - > getOperands ( ) ) {
if ( op_ptr - > getKind ( ) = = MachineOperand : : KIND_REG ) {
auto reg_op = static_cast < RegOperand * > ( op_ptr . get ( ) ) ;
if ( reg_op - > isVirtual ( ) ) {
unsigned vreg = reg_op - > getVRegNum ( ) ;
if ( DEEPERDEBUG ) std : : cerr < < " %v " < < vreg < < " -> " ;
if ( vreg_to_preg_map . count ( vreg ) ) {
reg_op - > setPReg ( vreg_to_preg_map . at ( vreg ) ) ;
PhysicalReg preg = vreg_to_preg_map . at ( vreg ) ;
reg_op - > setPReg ( preg ) ;
if ( DEEPERDEBUG ) std : : cerr < < pregToString ( preg ) < < " , " ;
} else {
// 如果一个vreg最终没有颜色, 这通常意味着它是一个短生命周期的临时变量
// 在溢出重写中产生,但在下一轮分配前就被优化掉了。
// 或者是一个从未被使用的定义。
// 给他一个临时寄存器以防万一。
reg_op - > setPReg ( PhysicalReg : : T5 ) ;
if ( DEEPERDEBUG ) std : : cerr < < " T5 (uncolored), " ;
}
}
} else if ( op_ptr - > getKind ( ) = = MachineOperand : : KIND_MEM ) {
@@ -445,24 +541,26 @@ void RISCv64LinearScan::applyAllocation() {
auto reg_op = mem_op - > getBase ( ) ;
if ( reg_op - > isVirtual ( ) ) {
unsigned vreg = reg_op - > getVRegNum ( ) ;
if ( DEEPERDEBUG ) std : : cerr < < " mem[%v " < < vreg < < " ] -> " ;
if ( vreg_to_preg_map . count ( vreg ) ) {
reg_op - > setPReg ( vreg_to_preg_map . at ( vreg ) ) ;
PhysicalReg preg = vreg_to_preg_map . at ( vreg ) ;
reg_op - > setPReg ( preg ) ;
if ( DEEPERDEBUG ) std : : cerr < < " mem[ " < < pregToString ( preg ) < < " ], " ;
} else {
reg_op - > setPReg ( PhysicalReg : : T5 ) ;
if ( DEEPERDEBUG ) std : : cerr < < " mem[T5] (uncolored), " ;
}
}
}
}
if ( DEEPERDEBUG ) std : : cerr < < " \n " ;
}
}
}
void RISCv64LinearScan : : getInstrUseDef ( const MachineInstr * instr , std : : set < unsigned > & use , std : : set < unsigned > & def ) {
// 这个函数与图着色版本中的 getInstrUseDef 逻辑完全相同,此处直接复用
auto opcode = instr - > getOpcode ( ) ;
const auto & operands = instr - > getOperands ( ) ;
// op_info 的定义已被移到函数外部的命名空间中
auto get_vreg_id_if_virtual = [ & ] ( const MachineOperand * op , std : : set < unsigned > & s ) {
if ( op - > getKind ( ) = = MachineOperand : : KIND_REG ) {
@@ -479,23 +577,17 @@ void RISCv64LinearScan::getInstrUseDef(const MachineInstr* instr, std::set<unsig
const auto & info = op_info . at ( opcode ) ;
for ( int idx : info . first ) if ( idx < operands . size ( ) ) get_vreg_id_if_virtual ( operands [ idx ] . get ( ) , def ) ;
for ( int idx : info . second ) if ( idx < operands . size ( ) ) get_vreg_id_if_virtual ( operands [ idx ] . get ( ) , use ) ;
// MemOperand 的基址寄存器总是一个 use
for ( const auto & op : operands ) if ( op - > getKind ( ) = = MachineOperand : : KIND_MEM ) get_vreg_id_if_virtual ( op . get ( ) , use ) ;
} else if ( opcode = = RVOpcodes : : CALL ) {
// CALL指令的特殊处理
// 第一个操作数( 如果有) 是def( 返回值)
if ( ! operands . empty ( ) & & operands [ 0 ] - > getKind ( ) = = MachineOperand : : KIND_REG ) get_vreg_id_if_virtual ( operands [ 0 ] . get ( ) , def ) ;
// 后续的寄存器操作数是use( 参数)
for ( size_t i = 1 ; i < operands . size ( ) ; + + i ) if ( operands [ i ] - > getKind ( ) = = MachineOperand : : KIND_REG ) get_vreg_id_if_virtual ( operands [ i ] . get ( ) , use ) ;
}
}
// 辅助函数: 判断是否为浮点vreg
bool RISCv64LinearScan : : isFPVReg ( unsigned vreg ) const {
return vreg_type_map . count ( vreg ) & & vreg_type_map . at ( vreg ) - > isFloat ( ) ;
}
// 辅助函数: 收集被使用的被调用者保存寄存器
void RISCv64LinearScan : : collectUsedCalleeSavedRegs ( ) {
StackFrameInfo & frame_info = MFunc - > getFrameInfo ( ) ;
frame_info . used_callee_saved_regs . clear ( ) ;
@@ -504,7 +596,7 @@ void RISCv64LinearScan::collectUsedCalleeSavedRegs() {
const auto & callee_saved_fp = getCalleeSavedFpRegs ( ) ;
std : : set < PhysicalReg > callee_saved_set ( callee_saved_int . begin ( ) , callee_saved_int . end ( ) ) ;
callee_saved_set . insert ( callee_saved_fp . begin ( ) , callee_saved_fp . end ( ) ) ;
callee_saved_set . insert ( PhysicalReg : : S0 ) ; // s0总是被用作帧指针
callee_saved_set . insert ( PhysicalReg : : S0 ) ;
for ( const auto & pair : vreg_to_preg_map ) {
PhysicalReg preg = pair . second ;