[backend]继续增强寄存器分配器健壮性
This commit is contained in:
61
src/include/backend/RISCv64/RISCv64BasicBlockAlloc.h
Normal file
61
src/include/backend/RISCv64/RISCv64BasicBlockAlloc.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef RISCV64_BASICBLOCKALLOC_H
|
||||
#define RISCV64_BASICBLOCKALLOC_H
|
||||
|
||||
#include "RISCv64LLIR.h"
|
||||
#include "RISCv64ISel.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
/**
|
||||
* @class RISCv64BasicBlockAlloc
|
||||
* @brief 一个有状态的、基本块级的贪心寄存器分配器。
|
||||
*
|
||||
* 该分配器作为简单但可靠的实现,它逐个处理基本块,并在块内尽可能地
|
||||
* 将虚拟寄存器的值保留在物理寄存器中,以减少不必要的内存访问。
|
||||
*/
|
||||
class RISCv64BasicBlockAlloc {
|
||||
public:
|
||||
RISCv64BasicBlockAlloc(MachineFunction* mfunc);
|
||||
void run();
|
||||
|
||||
private:
|
||||
void computeLiveness();
|
||||
void processBasicBlock(MachineBasicBlock* mbb);
|
||||
void assignStackSlotsForAllVRegs();
|
||||
|
||||
// 核心分配函数
|
||||
PhysicalReg ensureInReg(unsigned vreg, std::vector<std::unique_ptr<MachineInstr>>& new_instrs);
|
||||
PhysicalReg allocReg(unsigned vreg, std::vector<std::unique_ptr<MachineInstr>>& new_instrs);
|
||||
PhysicalReg findFreeReg(bool is_fp);
|
||||
PhysicalReg spillReg(bool is_fp, std::vector<std::unique_ptr<MachineInstr>>& new_instrs);
|
||||
|
||||
// 状态跟踪(每个基本块开始时都会重置)
|
||||
std::map<unsigned, PhysicalReg> vreg_to_preg; // 当前vreg到物理寄存器的映射
|
||||
std::map<PhysicalReg, unsigned> preg_to_vreg; // 反向映射
|
||||
std::set<PhysicalReg> dirty_pregs; // 被修改过、需要写回的物理寄存器
|
||||
|
||||
// 分配器全局信息
|
||||
MachineFunction* MFunc;
|
||||
RISCv64ISel* ISel;
|
||||
std::map<unsigned, PhysicalReg> abi_vreg_map; // 函数参数的ABI寄存器映射
|
||||
|
||||
// 寄存器池和循环索引
|
||||
std::vector<PhysicalReg> int_temps;
|
||||
std::vector<PhysicalReg> fp_temps;
|
||||
int int_temp_idx = 0;
|
||||
int fp_temp_idx = 0;
|
||||
|
||||
// 辅助函数
|
||||
PhysicalReg getNextIntTemp();
|
||||
PhysicalReg getNextFpTemp();
|
||||
|
||||
// 活性分析结果
|
||||
std::map<const MachineBasicBlock*, std::set<unsigned>> live_out;
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
#endif // RISCV64_BASICBLOCKALLOC_H
|
||||
@@ -255,6 +255,19 @@ public:
|
||||
void addOperand(std::unique_ptr<MachineOperand> operand) {
|
||||
operands.push_back(std::move(operand));
|
||||
}
|
||||
/**
|
||||
* @brief (为紧急溢出模式添加)将指令中所有对特定虚拟寄存器的引用替换为指定的物理寄存器。
|
||||
* * @param old_vreg 需要被替换的虚拟寄存器号。
|
||||
* @param preg 用于替换的物理寄存器。
|
||||
*/
|
||||
void replaceVRegWithPReg(unsigned old_vreg, PhysicalReg preg);
|
||||
|
||||
/**
|
||||
* @brief (为常规溢出模式添加)根据提供的映射表,重映射指令中的虚拟寄存器。
|
||||
* * @param use_remap 一个从旧vreg到新vreg的映射,用于指令的use操作数。
|
||||
* @param def_remap 一个从旧vreg到新vreg的映射,用于指令的def操作数。
|
||||
*/
|
||||
void remapVRegs(const std::map<unsigned, unsigned>& use_remap, const std::map<unsigned, unsigned>& def_remap);
|
||||
private:
|
||||
RVOpcodes opcode;
|
||||
std::vector<std::unique_ptr<MachineOperand>> operands;
|
||||
@@ -319,6 +332,22 @@ private:
|
||||
std::vector<std::unique_ptr<MachineBasicBlock>> blocks;
|
||||
StackFrameInfo frame_info;
|
||||
};
|
||||
inline bool isMemoryOp(RVOpcodes opcode) {
|
||||
switch (opcode) {
|
||||
case RVOpcodes::LB: case RVOpcodes::LH: case RVOpcodes::LW: case RVOpcodes::LD:
|
||||
case RVOpcodes::LBU: case RVOpcodes::LHU: case RVOpcodes::LWU:
|
||||
case RVOpcodes::SB: case RVOpcodes::SH: case RVOpcodes::SW: case RVOpcodes::SD:
|
||||
case RVOpcodes::FLW:
|
||||
case RVOpcodes::FSW:
|
||||
case RVOpcodes::FLD:
|
||||
case RVOpcodes::FSD:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void getInstrUseDef(const MachineInstr* instr, std::set<unsigned>& use, std::set<unsigned>& def);
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ struct LiveInterval {
|
||||
class RISCv64LinearScan {
|
||||
public:
|
||||
RISCv64LinearScan(MachineFunction* mfunc);
|
||||
void run();
|
||||
bool run();
|
||||
|
||||
private:
|
||||
// --- 核心算法流程 ---
|
||||
@@ -45,11 +45,9 @@ private:
|
||||
bool linearScan();
|
||||
void rewriteProgram();
|
||||
void applyAllocation();
|
||||
void chooseRegForInterval(LiveInterval* current);
|
||||
void spillAtInterval(LiveInterval* current);
|
||||
|
||||
// --- 辅助函数 ---
|
||||
void getInstrUseDef(const MachineInstr* instr, std::set<unsigned>& use, std::set<unsigned>& def);
|
||||
bool isFPVReg(unsigned vreg) const;
|
||||
void collectUsedCalleeSavedRegs();
|
||||
|
||||
@@ -66,11 +64,12 @@ private:
|
||||
|
||||
std::set<unsigned> spilled_vregs; // 记录在本轮被决定溢出的vreg
|
||||
|
||||
bool conservative_spill_mode = false;
|
||||
const PhysicalReg SPILL_TEMP_REG = PhysicalReg::T4;
|
||||
|
||||
// --- 寄存器池和分配结果 ---
|
||||
std::vector<PhysicalReg> allocable_int_regs;
|
||||
std::vector<PhysicalReg> allocable_fp_regs;
|
||||
std::set<PhysicalReg> free_int_regs;
|
||||
std::set<PhysicalReg> free_fp_regs;
|
||||
std::map<unsigned, PhysicalReg> vreg_to_preg_map;
|
||||
std::map<unsigned, PhysicalReg> abi_vreg_map;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user