Files
mysysy/src/backend/RISCv64/Handler/LegalizeImmediates.cpp

171 lines
7.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "LegalizeImmediates.h"
#include "RISCv64ISel.h" // 需要包含它以调用 getNewVReg()
#include "RISCv64AsmPrinter.h"
#include <vector>
#include <iostream>
// 声明外部调试控制变量
extern int DEBUG;
extern int DEEPDEBUG;
namespace sysy {
char LegalizeImmediatesPass::ID = 0;
// 辅助函数检查一个立即数是否在RISC-V的12位有符号范围内
static bool isLegalImmediate(int64_t imm) {
return imm >= -2048 && imm <= 2047;
}
void LegalizeImmediatesPass::runOnMachineFunction(MachineFunction* mfunc) {
if (DEBUG) {
std::cerr << "===== Running Legalize Immediates Pass on function: " << mfunc->getName() << " =====\n";
}
// 定义我们保留的、用于暂存的物理寄存器
const PhysicalReg TEMP_REG = PhysicalReg::T5;
// 创建一个临时的AsmPrinter用于打印指令方便调试
RISCv64AsmPrinter temp_printer(mfunc);
if (DEEPDEBUG) {
temp_printer.setStream(std::cerr);
}
for (auto& mbb : mfunc->getBlocks()) {
if (DEEPDEBUG) {
std::cerr << "--- Processing Basic Block: " << mbb->getName() << " ---\n";
}
// 创建一个新的指令列表,用于存放合法化后的指令
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) {
if (DEEPDEBUG) {
std::cerr << " Checking: ";
// 打印指令时末尾会带换行符,所以这里不用 std::endl
temp_printer.printInstruction(instr_ptr.get(), true);
}
bool legalized = false; // 标记当前指令是否已被展开处理
switch (instr_ptr->getOpcode()) {
case RVOpcodes::ADDI:
case RVOpcodes::ADDIW: {
auto& operands = instr_ptr->getOperands();
// 确保操作数足够多,以防万一
if (operands.size() < 3) break;
auto imm_op = static_cast<ImmOperand*>(operands.back().get());
if (!isLegalImmediate(imm_op->getValue())) {
if (DEEPDEBUG) {
std::cerr << " >> ILLEGAL immediate (" << imm_op->getValue() << "). Expanding...\n";
}
// 立即数超出范围,需要展开
auto rd_op = std::make_unique<RegOperand>(*static_cast<RegOperand*>(operands[0].get()));
auto rs1_op = std::make_unique<RegOperand>(*static_cast<RegOperand*>(operands[1].get()));
// 1. li t5, immediate
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(TEMP_REG));
li->addOperand(std::make_unique<ImmOperand>(imm_op->getValue()));
// 2. add/addw rd, rs1, t5
auto new_op = (instr_ptr->getOpcode() == RVOpcodes::ADDI) ? RVOpcodes::ADD : RVOpcodes::ADDW;
auto add = std::make_unique<MachineInstr>(new_op);
add->addOperand(std::move(rd_op));
add->addOperand(std::move(rs1_op));
add->addOperand(std::make_unique<RegOperand>(TEMP_REG));
if (DEEPDEBUG) {
std::cerr << " New sequence:\n ";
temp_printer.printInstruction(li.get(), true);
std::cerr << " ";
temp_printer.printInstruction(add.get(), true);
}
new_instructions.push_back(std::move(li));
new_instructions.push_back(std::move(add));
legalized = true;
}
break;
}
// 处理所有内存加载/存储指令
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: {
auto& operands = instr_ptr->getOperands();
auto mem_op = static_cast<MemOperand*>(operands.back().get());
auto offset_op = mem_op->getOffset();
if (!isLegalImmediate(offset_op->getValue())) {
if (DEEPDEBUG) {
std::cerr << " >> ILLEGAL immediate offset (" << offset_op->getValue() << "). Expanding...\n";
}
// 偏移量超出范围,需要展开
auto data_reg_op = std::make_unique<RegOperand>(*static_cast<RegOperand*>(operands[0].get()));
auto base_reg_op = std::make_unique<RegOperand>(*mem_op->getBase());
// 1. li t5, offset
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(TEMP_REG));
li->addOperand(std::make_unique<ImmOperand>(offset_op->getValue()));
// 2. add t5, base_reg, t5 (计算最终地址结果也放在t5)
auto add = std::make_unique<MachineInstr>(RVOpcodes::ADD);
add->addOperand(std::make_unique<RegOperand>(TEMP_REG));
add->addOperand(std::move(base_reg_op));
add->addOperand(std::make_unique<RegOperand>(TEMP_REG));
// 3. lw/sw data_reg, 0(t5)
auto mem_instr = std::make_unique<MachineInstr>(instr_ptr->getOpcode());
mem_instr->addOperand(std::move(data_reg_op));
mem_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(TEMP_REG),
std::make_unique<ImmOperand>(0)
));
if (DEEPDEBUG) {
std::cerr << " New sequence:\n ";
temp_printer.printInstruction(li.get(), true);
std::cerr << " ";
temp_printer.printInstruction(add.get(), true);
std::cerr << " ";
temp_printer.printInstruction(mem_instr.get(), true);
}
new_instructions.push_back(std::move(li));
new_instructions.push_back(std::move(add));
new_instructions.push_back(std::move(mem_instr));
legalized = true;
}
break;
}
default:
// 其他指令不需要处理
break;
}
if (!legalized) {
if (DEEPDEBUG) {
std::cerr << " -- Immediate is legal. Skipping.\n";
}
// 如果当前指令不需要合法化,直接将其移动到新列表中
new_instructions.push_back(std::move(instr_ptr));
}
}
// 用新的、已合法化的指令列表替换旧的列表
mbb->getInstructions() = std::move(new_instructions);
}
if (DEBUG) {
std::cerr << "===== Finished Legalize Immediates Pass =====\n\n";
}
}
} // namespace sysy