Compare commits
15 Commits
buildcfg
...
backend-IR
| Author | SHA1 | Date | |
|---|---|---|---|
| 004ef82488 | |||
| 8f1d592d4e | |||
| 537533ee43 | |||
| bfe218be07 | |||
| 384f7c548b | |||
| 57fe17dc21 | |||
| e48cddab9f | |||
| aef10b48e8 | |||
| 373726b02f | |||
| a0b69f20fb | |||
| 8fe9867f33 | |||
| 166d0fc372 | |||
| 873dbf64d0 | |||
| f387aecc03 | |||
| 03e88eee70 |
@ -68,7 +68,7 @@ display_file_content() {
|
||||
fi
|
||||
}
|
||||
|
||||
# --- 本次修改点: 整个参数解析逻辑被重写 ---
|
||||
# --- 参数解析 ---
|
||||
# 使用标准的 while 循环来健壮地处理任意顺序的参数
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case "$1" in
|
||||
@ -164,6 +164,16 @@ for sy_file in "${SY_FILES[@]}"; do
|
||||
echo "======================================================================"
|
||||
echo "正在处理: ${sy_file}"
|
||||
|
||||
# --- 本次修改点: 拷贝源文件到 tmp 目录 ---
|
||||
echo " 拷贝源文件到 ${TMP_DIR}..."
|
||||
cp "${sy_file}" "${TMP_DIR}/$(basename "${sy_file}")"
|
||||
if [ -f "${input_file}" ]; then
|
||||
cp "${input_file}" "${TMP_DIR}/$(basename "${input_file}")"
|
||||
fi
|
||||
if [ -f "${output_reference_file}" ]; then
|
||||
cp "${output_reference_file}" "${TMP_DIR}/$(basename "${output_reference_file}")"
|
||||
fi
|
||||
|
||||
# 步骤 1: sysyc 编译
|
||||
echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..."
|
||||
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s ir "${sy_file}" > "${ir_file}"
|
||||
|
||||
@ -8,6 +8,7 @@ add_library(riscv64_backend_lib STATIC
|
||||
Handler/CalleeSavedHandler.cpp
|
||||
Handler/LegalizeImmediates.cpp
|
||||
Handler/PrologueEpilogueInsertion.cpp
|
||||
Handler/EliminateFrameIndices.cpp
|
||||
Optimize/Peephole.cpp
|
||||
Optimize/PostRA_Scheduler.cpp
|
||||
Optimize/PreRA_Scheduler.cpp
|
||||
|
||||
@ -8,11 +8,6 @@ namespace sysy {
|
||||
|
||||
char CalleeSavedHandler::ID = 0;
|
||||
|
||||
// 辅助函数,用于判断一个物理寄存器是否为浮点寄存器
|
||||
static bool is_fp_reg(PhysicalReg reg) {
|
||||
return reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31;
|
||||
}
|
||||
|
||||
bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||
// This pass works on MachineFunction level, not IR level
|
||||
return false;
|
||||
@ -20,114 +15,37 @@ bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||
|
||||
void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||
|
||||
std::set<PhysicalReg> used_callee_saved;
|
||||
|
||||
// 1. 扫描所有指令,找出被使用的callee-saved寄存器
|
||||
// 这个Pass在RegAlloc之后运行,所以可以访问到物理寄存器
|
||||
for (auto& mbb : mfunc->getBlocks()) {
|
||||
for (auto& instr : mbb->getInstructions()) {
|
||||
for (auto& op : instr->getOperands()) {
|
||||
|
||||
auto check_and_insert_reg = [&](RegOperand* reg_op) {
|
||||
if (reg_op && !reg_op->isVirtual()) {
|
||||
PhysicalReg preg = reg_op->getPReg();
|
||||
|
||||
// 检查整数 s1-s11
|
||||
if (preg >= PhysicalReg::S1 && preg <= PhysicalReg::S11) {
|
||||
used_callee_saved.insert(preg);
|
||||
}
|
||||
// 检查浮点 fs0-fs11 (f8,f9,f18-f27)
|
||||
else if ((preg >= PhysicalReg::F8 && preg <= PhysicalReg::F9) || (preg >= PhysicalReg::F18 && preg <= PhysicalReg::F27)) {
|
||||
used_callee_saved.insert(preg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (op->getKind() == MachineOperand::KIND_REG) {
|
||||
check_and_insert_reg(static_cast<RegOperand*>(op.get()));
|
||||
} else if (op->getKind() == MachineOperand::KIND_MEM) {
|
||||
check_and_insert_reg(static_cast<MemOperand*>(op.get())->getBase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const std::set<PhysicalReg>& used_callee_saved = frame_info.used_callee_saved_regs;
|
||||
|
||||
if (used_callee_saved.empty()) {
|
||||
frame_info.callee_saved_size = 0;
|
||||
frame_info.callee_saved_regs_to_store.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 计算并更新 frame_info
|
||||
frame_info.callee_saved_size = used_callee_saved.size() * 8;
|
||||
|
||||
// 为了布局确定性和恢复顺序一致,对寄存器排序
|
||||
std::vector<PhysicalReg> sorted_regs(used_callee_saved.begin(), used_callee_saved.end());
|
||||
std::sort(sorted_regs.begin(), sorted_regs.end());
|
||||
|
||||
// 3. 在函数序言中插入保存指令
|
||||
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
||||
auto& entry_instrs = entry_block->getInstructions();
|
||||
// 插入点在函数入口标签之后,或者就是最开始
|
||||
auto insert_pos = entry_instrs.begin();
|
||||
if (!entry_instrs.empty() && entry_instrs.front()->getOpcode() == RVOpcodes::LABEL) {
|
||||
insert_pos = std::next(insert_pos);
|
||||
// 1. 计算被调用者保存寄存器所需的总空间大小
|
||||
// s0 总是由 PEI Pass 单独处理,这里不计入大小,但要确保它在列表中
|
||||
int size = 0;
|
||||
std::set<PhysicalReg> regs_to_save = used_callee_saved;
|
||||
if (regs_to_save.count(PhysicalReg::S0)) {
|
||||
regs_to_save.erase(PhysicalReg::S0);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<MachineInstr>> save_instrs;
|
||||
// [关键] 从局部变量区域之后开始分配空间
|
||||
int current_offset = - (16 + frame_info.locals_size);
|
||||
size = regs_to_save.size() * 8; // 每个寄存器占8字节 (64-bit)
|
||||
frame_info.callee_saved_size = size;
|
||||
|
||||
for (PhysicalReg reg : sorted_regs) {
|
||||
current_offset -= 8;
|
||||
RVOpcodes save_op = is_fp_reg(reg) ? RVOpcodes::FSD : RVOpcodes::SD;
|
||||
// 2. 创建一个有序的、需要保存的寄存器列表,以便后续 Pass 确定地生成代码
|
||||
// s0 不应包含在此列表中,因为它由 PEI Pass 特殊处理
|
||||
std::vector<PhysicalReg> sorted_regs(regs_to_save.begin(), regs_to_save.end());
|
||||
std::sort(sorted_regs.begin(), sorted_regs.end(), [](PhysicalReg a, PhysicalReg b){
|
||||
return static_cast<int>(a) < static_cast<int>(b);
|
||||
});
|
||||
frame_info.callee_saved_regs_to_store = sorted_regs;
|
||||
|
||||
auto save_instr = std::make_unique<MachineInstr>(save_op);
|
||||
save_instr->addOperand(std::make_unique<RegOperand>(reg));
|
||||
save_instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址为帧指针 s0
|
||||
std::make_unique<ImmOperand>(current_offset)
|
||||
));
|
||||
save_instrs.push_back(std::move(save_instr));
|
||||
}
|
||||
|
||||
if (!save_instrs.empty()) {
|
||||
entry_instrs.insert(insert_pos,
|
||||
std::make_move_iterator(save_instrs.begin()),
|
||||
std::make_move_iterator(save_instrs.end()));
|
||||
}
|
||||
|
||||
// 4. 在函数结尾(ret之前)插入恢复指令
|
||||
for (auto& mbb : mfunc->getBlocks()) {
|
||||
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
||||
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
||||
std::vector<std::unique_ptr<MachineInstr>> restore_instrs;
|
||||
// [关键] 使用与保存时完全相同的逻辑来计算偏移量
|
||||
current_offset = - (16 + frame_info.locals_size);
|
||||
|
||||
for (PhysicalReg reg : sorted_regs) {
|
||||
current_offset -= 8;
|
||||
RVOpcodes restore_op = is_fp_reg(reg) ? RVOpcodes::FLD : RVOpcodes::LD;
|
||||
|
||||
auto restore_instr = std::make_unique<MachineInstr>(restore_op);
|
||||
restore_instr->addOperand(std::make_unique<RegOperand>(reg));
|
||||
restore_instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||
std::make_unique<ImmOperand>(current_offset)
|
||||
));
|
||||
restore_instrs.push_back(std::move(restore_instr));
|
||||
}
|
||||
|
||||
if (!restore_instrs.empty()) {
|
||||
mbb->getInstructions().insert(it,
|
||||
std::make_move_iterator(restore_instrs.begin()),
|
||||
std::make_move_iterator(restore_instrs.end()));
|
||||
}
|
||||
goto next_block_label;
|
||||
}
|
||||
}
|
||||
next_block_label:;
|
||||
}
|
||||
// 3. [关键修正] 更新栈帧总大小。
|
||||
// 这是初步计算,PEI Pass 会进行最终的对齐。
|
||||
frame_info.total_size = frame_info.locals_size +
|
||||
frame_info.spill_size +
|
||||
frame_info.callee_saved_size;
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
} // namespace sysy
|
||||
|
||||
198
src/backend/RISCv64/Handler/EliminateFrameIndices.cpp
Normal file
198
src/backend/RISCv64/Handler/EliminateFrameIndices.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
#include "EliminateFrameIndices.h"
|
||||
#include "RISCv64ISel.h"
|
||||
#include <cassert>
|
||||
#include <vector> // [新增] 为插入指令而包含
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// getTypeSizeInBytes 是一个通用辅助函数,保持不变
|
||||
unsigned EliminateFrameIndicesPass::getTypeSizeInBytes(Type* type) {
|
||||
if (!type) {
|
||||
assert(false && "Cannot get size of a null type.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (type->getKind()) {
|
||||
case Type::kInt:
|
||||
case Type::kFloat:
|
||||
return 4;
|
||||
case Type::kPointer:
|
||||
return 8;
|
||||
case Type::kArray: {
|
||||
auto arrayType = type->as<ArrayType>();
|
||||
return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType());
|
||||
}
|
||||
default:
|
||||
assert(false && "Unsupported type for size calculation.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
|
||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||
Function* F = mfunc->getFunc();
|
||||
RISCv64ISel* isel = mfunc->getISel();
|
||||
|
||||
// 1. [已移除] 不再处理栈传递的参数
|
||||
// 原先处理栈参数 (arg_idx >= 8) 的逻辑已被移除。
|
||||
// 这项职责已完全转移到 PrologueEpilogueInsertionPass,以避免逻辑冲突和错误。
|
||||
// [注释更新] -> 上述注释已过时。根据新方案,我们将在这里处理栈传递的参数,
|
||||
// 以便在寄存器分配前就将数据流显式化,修复溢出逻辑的BUG。
|
||||
|
||||
// 2. 只为局部变量(AllocaInst)分配栈空间和计算偏移量
|
||||
// 局部变量从 s0 下方(负偏移量)开始分配,紧接着为 ra 和 s0 预留的16字节之后
|
||||
int local_var_offset = 16;
|
||||
|
||||
if(F) { // 确保函数指针有效
|
||||
for (auto& bb : F->getBasicBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
|
||||
Type* allocated_type = alloca->getType()->as<PointerType>()->getBaseType();
|
||||
int size = getTypeSizeInBytes(allocated_type);
|
||||
|
||||
// RISC-V要求栈地址8字节对齐
|
||||
size = (size + 7) & ~7;
|
||||
if (size == 0) size = 8; // 至少分配8字节
|
||||
|
||||
local_var_offset += size;
|
||||
unsigned alloca_vreg = isel->getVReg(alloca);
|
||||
// 局部变量使用相对于s0的负向偏移
|
||||
frame_info.alloca_offsets[alloca_vreg] = -local_var_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 记录仅由AllocaInst分配的局部变量的总大小
|
||||
frame_info.locals_size = local_var_offset - 16;
|
||||
|
||||
// 3. [核心修改] 在函数入口为所有栈传递的参数插入load指令
|
||||
// 这个步骤至关重要:它在寄存器分配之前,为这些参数的vreg创建了明确的“定义(def)”指令。
|
||||
// 这解决了在高寄存器压力下,当这些vreg被溢出时,`rewriteProgram`找不到其定义点而崩溃的问题。
|
||||
if (F && isel && !mfunc->getBlocks().empty()) {
|
||||
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
||||
std::vector<std::unique_ptr<MachineInstr>> arg_load_instrs;
|
||||
int arg_idx = 0;
|
||||
for (Argument* arg : F->getArguments()) {
|
||||
// 根据ABI,前8个整型/指针参数通过寄存器传递,这里只处理超出部分。
|
||||
if (arg_idx >= 8) {
|
||||
// 计算参数在调用者栈帧中的位置,该位置相对于被调用者的帧指针s0是正向偏移。
|
||||
// 第9个参数(arg_idx=8)位于 0(s0),第10个(arg_idx=9)位于 8(s0),以此类推。
|
||||
int offset = (arg_idx - 8) * 8;
|
||||
unsigned arg_vreg = isel->getVReg(arg);
|
||||
Type* arg_type = arg->getType();
|
||||
|
||||
// 根据参数类型选择正确的加载指令
|
||||
RVOpcodes load_op;
|
||||
if (arg_type->isFloat()) {
|
||||
load_op = RVOpcodes::FLW; // 单精度浮点
|
||||
} else if (arg_type->isPointer()) {
|
||||
load_op = RVOpcodes::LD; // 64位指针
|
||||
} else {
|
||||
load_op = RVOpcodes::LW; // 32位整数
|
||||
}
|
||||
|
||||
// 创建加载指令: lw/ld/flw vreg, offset(s0)
|
||||
auto load_instr = std::make_unique<MachineInstr>(load_op);
|
||||
load_instr->addOperand(std::make_unique<RegOperand>(arg_vreg));
|
||||
load_instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址为帧指针
|
||||
std::make_unique<ImmOperand>(offset)
|
||||
));
|
||||
arg_load_instrs.push_back(std::move(load_instr));
|
||||
}
|
||||
arg_idx++;
|
||||
}
|
||||
|
||||
// 将所有新创建的参数加载指令一次性插入到入口块的起始位置
|
||||
auto& entry_instrs = entry_block->getInstructions();
|
||||
entry_instrs.insert(entry_instrs.begin(),
|
||||
std::make_move_iterator(arg_load_instrs.begin()),
|
||||
std::make_move_iterator(arg_load_instrs.end()));
|
||||
}
|
||||
|
||||
|
||||
// 4. 遍历所有机器指令,将访问局部变量的伪指令展开为真实指令
|
||||
// 由于处理参数的逻辑已移除,这里的展开现在只针对局部变量,因此是正确的。
|
||||
// [注释更新] -> 上述注释已过时。此部分逻辑保持不变,它正确地处理了局部变量。
|
||||
for (auto& mbb : mfunc->getBlocks()) {
|
||||
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
|
||||
for (auto& instr_ptr : mbb->getInstructions()) {
|
||||
RVOpcodes opcode = instr_ptr->getOpcode();
|
||||
|
||||
if (opcode == RVOpcodes::FRAME_LOAD_W || opcode == RVOpcodes::FRAME_LOAD_D || opcode == RVOpcodes::FRAME_LOAD_F) {
|
||||
RVOpcodes real_load_op;
|
||||
if (opcode == RVOpcodes::FRAME_LOAD_W) real_load_op = RVOpcodes::LW;
|
||||
else if (opcode == RVOpcodes::FRAME_LOAD_D) real_load_op = RVOpcodes::LD;
|
||||
else real_load_op = RVOpcodes::FLW;
|
||||
|
||||
auto& operands = instr_ptr->getOperands();
|
||||
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
|
||||
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
|
||||
int offset = frame_info.alloca_offsets.at(alloca_vreg);
|
||||
auto addr_vreg = isel->getNewVReg(Type::getPointerType(Type::getIntType()));
|
||||
|
||||
// 展开为: addi addr_vreg, s0, offset
|
||||
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
|
||||
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||
addi->addOperand(std::make_unique<ImmOperand>(offset));
|
||||
new_instructions.push_back(std::move(addi));
|
||||
|
||||
// 展开为: lw/ld/flw dest_vreg, 0(addr_vreg)
|
||||
auto load_instr = std::make_unique<MachineInstr>(real_load_op);
|
||||
load_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
load_instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(addr_vreg),
|
||||
std::make_unique<ImmOperand>(0)));
|
||||
new_instructions.push_back(std::move(load_instr));
|
||||
|
||||
} else if (opcode == RVOpcodes::FRAME_STORE_W || opcode == RVOpcodes::FRAME_STORE_D || opcode == RVOpcodes::FRAME_STORE_F) {
|
||||
RVOpcodes real_store_op;
|
||||
if (opcode == RVOpcodes::FRAME_STORE_W) real_store_op = RVOpcodes::SW;
|
||||
else if (opcode == RVOpcodes::FRAME_STORE_D) real_store_op = RVOpcodes::SD;
|
||||
else real_store_op = RVOpcodes::FSW;
|
||||
|
||||
auto& operands = instr_ptr->getOperands();
|
||||
unsigned src_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
|
||||
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
|
||||
int offset = frame_info.alloca_offsets.at(alloca_vreg);
|
||||
auto addr_vreg = isel->getNewVReg(Type::getPointerType(Type::getIntType()));
|
||||
|
||||
// 展开为: addi addr_vreg, s0, offset
|
||||
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
|
||||
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||
addi->addOperand(std::make_unique<ImmOperand>(offset));
|
||||
new_instructions.push_back(std::move(addi));
|
||||
|
||||
// 展开为: sw/sd/fsw src_vreg, 0(addr_vreg)
|
||||
auto store_instr = std::make_unique<MachineInstr>(real_store_op);
|
||||
store_instr->addOperand(std::make_unique<RegOperand>(src_vreg));
|
||||
store_instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(addr_vreg),
|
||||
std::make_unique<ImmOperand>(0)));
|
||||
new_instructions.push_back(std::move(store_instr));
|
||||
|
||||
} else if (instr_ptr->getOpcode() == RVOpcodes::FRAME_ADDR) {
|
||||
auto& operands = instr_ptr->getOperands();
|
||||
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
|
||||
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
|
||||
int offset = frame_info.alloca_offsets.at(alloca_vreg);
|
||||
|
||||
// 将 `frame_addr rd, rs` 展开为 `addi rd, s0, offset`
|
||||
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
addi->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||
addi->addOperand(std::make_unique<ImmOperand>(offset));
|
||||
new_instructions.push_back(std::move(addi));
|
||||
|
||||
} else {
|
||||
new_instructions.push_back(std::move(instr_ptr));
|
||||
}
|
||||
}
|
||||
mbb->getInstructions() = std::move(new_instructions);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@ -1,17 +1,22 @@
|
||||
#include "PrologueEpilogueInsertion.h"
|
||||
#include "RISCv64LLIR.h" // 假设包含了 PhysicalReg, RVOpcodes 等定义
|
||||
#include "RISCv64ISel.h"
|
||||
#include "RISCv64RegAlloc.h" // 需要访问RegAlloc的结果
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
char PrologueEpilogueInsertionPass::ID = 0;
|
||||
|
||||
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
|
||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||
Function* F = mfunc->getFunc();
|
||||
RISCv64ISel* isel = mfunc->getISel();
|
||||
|
||||
// 1. 清理 KEEPALIVE 伪指令
|
||||
for (auto& mbb : mfunc->getBlocks()) {
|
||||
auto& instrs = mbb->getInstructions();
|
||||
|
||||
// 使用标准的 Erase-Remove Idiom 来删除满足条件的元素
|
||||
instrs.erase(
|
||||
std::remove_if(instrs.begin(), instrs.end(),
|
||||
[](const std::unique_ptr<MachineInstr>& instr) {
|
||||
@ -22,39 +27,55 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
||||
);
|
||||
}
|
||||
|
||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||
Function* F = mfunc->getFunc();
|
||||
RISCv64ISel* isel = mfunc->getISel();
|
||||
|
||||
// [关键] 获取寄存器分配的结果 (vreg -> preg 的映射)
|
||||
// RegAlloc Pass 必须已经运行过
|
||||
// 2. [新增] 确定需要保存的被调用者保存寄存器 (callee-saved)
|
||||
// 这部分逻辑从 CalleeSavedHandler Pass 移入,以集中管理序言生成
|
||||
auto& vreg_to_preg_map = frame_info.vreg_to_preg_map;
|
||||
std::set<PhysicalReg> used_callee_saved_regs_set;
|
||||
const auto& callee_saved_int = getCalleeSavedIntRegs();
|
||||
const auto& callee_saved_fp = getCalleeSavedFpRegs();
|
||||
|
||||
// 完全遵循 AsmPrinter 中的计算逻辑
|
||||
for (const auto& pair : vreg_to_preg_map) {
|
||||
PhysicalReg preg = pair.second;
|
||||
// 检查是否在整数或浮点 callee-saved 集合中
|
||||
// 注意:s0作为帧指针,由序言/尾声逻辑特殊处理,不在此处保存
|
||||
bool is_int_cs = std::find(callee_saved_int.begin(), callee_saved_int.end(), preg) != callee_saved_int.end();
|
||||
bool is_fp_cs = std::find(callee_saved_fp.begin(), callee_saved_fp.end(), preg) != callee_saved_fp.end();
|
||||
if ((is_int_cs && preg != PhysicalReg::S0) || is_fp_cs) {
|
||||
used_callee_saved_regs_set.insert(preg);
|
||||
}
|
||||
}
|
||||
// 为了确定性排序,并存入 frame_info 供尾声使用
|
||||
frame_info.callee_saved_regs_to_store.assign(
|
||||
used_callee_saved_regs_set.begin(), used_callee_saved_regs_set.end()
|
||||
);
|
||||
std::sort(frame_info.callee_saved_regs_to_store.begin(), frame_info.callee_saved_regs_to_store.end());
|
||||
frame_info.callee_saved_size = frame_info.callee_saved_regs_to_store.size() * 8; // 每个寄存器8字节
|
||||
|
||||
// 3. 计算最终的栈帧总大小
|
||||
int total_stack_size = frame_info.locals_size +
|
||||
frame_info.spill_size +
|
||||
frame_info.callee_saved_size +
|
||||
16; // 为 ra 和 s0 固定的16字节
|
||||
|
||||
int aligned_stack_size = (total_stack_size + 15) & ~15;
|
||||
int aligned_stack_size = (total_stack_size + 15) & ~15; // 16字节对齐
|
||||
frame_info.total_size = aligned_stack_size;
|
||||
|
||||
// 只有在需要分配栈空间时才生成指令
|
||||
// 只有在需要分配栈空间时才生成序言和尾声
|
||||
if (aligned_stack_size > 0) {
|
||||
// --- 1. 插入序言 ---
|
||||
// --- 4. 插入完整的序言 ---
|
||||
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
||||
auto& entry_instrs = entry_block->getInstructions();
|
||||
|
||||
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
|
||||
|
||||
// 1. addi sp, sp, -aligned_stack_size
|
||||
// 4.1. 分配栈帧: addi sp, sp, -aligned_stack_size
|
||||
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||
alloc_stack->addOperand(std::make_unique<ImmOperand>(-aligned_stack_size));
|
||||
prologue_instrs.push_back(std::move(alloc_stack));
|
||||
|
||||
// 2. sd ra, (aligned_stack_size - 8)(sp)
|
||||
// 4.2. 保存 ra 和 s0
|
||||
// sd ra, (aligned_stack_size - 8)(sp)
|
||||
auto save_ra = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
||||
save_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
||||
save_ra->addOperand(std::make_unique<MemOperand>(
|
||||
@ -62,8 +83,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
||||
std::make_unique<ImmOperand>(aligned_stack_size - 8)
|
||||
));
|
||||
prologue_instrs.push_back(std::move(save_ra));
|
||||
|
||||
// 3. sd s0, (aligned_stack_size - 16)(sp)
|
||||
// sd s0, (aligned_stack_size - 16)(sp)
|
||||
auto save_fp = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
||||
save_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||
save_fp->addOperand(std::make_unique<MemOperand>(
|
||||
@ -72,66 +92,60 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
||||
));
|
||||
prologue_instrs.push_back(std::move(save_fp));
|
||||
|
||||
// 4. addi s0, sp, aligned_stack_size
|
||||
// 4.3. 设置新的帧指针 s0: addi s0, sp, aligned_stack_size
|
||||
auto set_fp = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
||||
prologue_instrs.push_back(std::move(set_fp));
|
||||
|
||||
// --- 在s0设置完毕后,使用物理寄存器加载栈参数 ---
|
||||
if (F && isel) {
|
||||
int arg_idx = 0;
|
||||
for (Argument* arg : F->getArguments()) {
|
||||
if (arg_idx >= 8) {
|
||||
unsigned vreg = isel->getVReg(arg);
|
||||
|
||||
if (frame_info.alloca_offsets.count(vreg) && vreg_to_preg_map.count(vreg)) {
|
||||
int offset = frame_info.alloca_offsets.at(vreg);
|
||||
PhysicalReg dest_preg = vreg_to_preg_map.at(vreg);
|
||||
Type* arg_type = arg->getType();
|
||||
|
||||
if (arg_type->isFloat()) {
|
||||
auto load_arg = std::make_unique<MachineInstr>(RVOpcodes::FLW);
|
||||
load_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
|
||||
load_arg->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||
std::make_unique<ImmOperand>(offset)
|
||||
));
|
||||
prologue_instrs.push_back(std::move(load_arg));
|
||||
} else {
|
||||
RVOpcodes load_op = arg_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
|
||||
auto load_arg = std::make_unique<MachineInstr>(load_op);
|
||||
load_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
|
||||
load_arg->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||
std::make_unique<ImmOperand>(offset)
|
||||
));
|
||||
prologue_instrs.push_back(std::move(load_arg));
|
||||
}
|
||||
}
|
||||
}
|
||||
arg_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
// 确定插入点
|
||||
auto insert_pos = entry_instrs.begin();
|
||||
|
||||
// 一次性将所有序言指令插入
|
||||
if (!prologue_instrs.empty()) {
|
||||
entry_instrs.insert(insert_pos,
|
||||
std::make_move_iterator(prologue_instrs.begin()),
|
||||
std::make_move_iterator(prologue_instrs.end()));
|
||||
// 4.4. [新增] 保存所有使用到的被调用者保存寄存器
|
||||
// 它们保存在 s0 下方,紧接着 ra/s0 的位置
|
||||
int callee_saved_offset = -16;
|
||||
for (const auto& reg : frame_info.callee_saved_regs_to_store) {
|
||||
callee_saved_offset -= 8;
|
||||
RVOpcodes store_op = (reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31) ? RVOpcodes::FSD : RVOpcodes::SD;
|
||||
auto save_cs_reg = std::make_unique<MachineInstr>(store_op);
|
||||
save_cs_reg->addOperand(std::make_unique<RegOperand>(reg));
|
||||
save_cs_reg->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||
std::make_unique<ImmOperand>(callee_saved_offset)
|
||||
));
|
||||
prologue_instrs.push_back(std::move(save_cs_reg));
|
||||
}
|
||||
|
||||
// --- 2. 插入尾声 (此部分逻辑保持不变) ---
|
||||
// 4.5. [核心修改] 加载栈传递参数的逻辑已从此移除
|
||||
// 这项工作已经前移至 `EliminateFrameIndicesPass` 中完成,
|
||||
// 以确保在寄存器分配前就将相关虚拟寄存器定义,从而修复溢出逻辑的bug。
|
||||
|
||||
// 4.6. 将所有生成的序言指令一次性插入到函数入口
|
||||
entry_instrs.insert(entry_instrs.begin(),
|
||||
std::make_move_iterator(prologue_instrs.begin()),
|
||||
std::make_move_iterator(prologue_instrs.end()));
|
||||
|
||||
// --- 5. 插入完整的尾声 ---
|
||||
for (auto& mbb : mfunc->getBlocks()) {
|
||||
// [修正] 使用前向迭代器查找RET指令,以确保在正确的位置(RET之前)插入尾声。
|
||||
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
||||
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
||||
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
|
||||
|
||||
// 5.1. [新增] 恢复被调用者保存寄存器
|
||||
callee_saved_offset = -16;
|
||||
for (const auto& reg : frame_info.callee_saved_regs_to_store) {
|
||||
callee_saved_offset -= 8;
|
||||
RVOpcodes load_op = (reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31) ? RVOpcodes::FLD : RVOpcodes::LD;
|
||||
auto restore_cs_reg = std::make_unique<MachineInstr>(load_op);
|
||||
restore_cs_reg->addOperand(std::make_unique<RegOperand>(reg));
|
||||
restore_cs_reg->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||
std::make_unique<ImmOperand>(callee_saved_offset)
|
||||
));
|
||||
epilogue_instrs.push_back(std::move(restore_cs_reg));
|
||||
}
|
||||
|
||||
// 1. ld ra
|
||||
// 5.2. 恢复 ra 和 s0 (注意基址现在是sp)
|
||||
// ld ra, (aligned_stack_size - 8)(sp)
|
||||
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
||||
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
||||
restore_ra->addOperand(std::make_unique<MemOperand>(
|
||||
@ -139,8 +153,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
||||
std::make_unique<ImmOperand>(aligned_stack_size - 8)
|
||||
));
|
||||
epilogue_instrs.push_back(std::move(restore_ra));
|
||||
|
||||
// 2. ld s0
|
||||
// ld s0, (aligned_stack_size - 16)(sp)
|
||||
auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
||||
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||
restore_fp->addOperand(std::make_unique<MemOperand>(
|
||||
@ -149,18 +162,19 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
||||
));
|
||||
epilogue_instrs.push_back(std::move(restore_fp));
|
||||
|
||||
// 3. addi sp, sp, aligned_stack_size
|
||||
// 5.3. 释放栈帧: addi sp, sp, aligned_stack_size
|
||||
auto dealloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||
dealloc_stack->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
||||
epilogue_instrs.push_back(std::move(dealloc_stack));
|
||||
|
||||
if (!epilogue_instrs.empty()) {
|
||||
mbb->getInstructions().insert(it,
|
||||
std::make_move_iterator(epilogue_instrs.begin()),
|
||||
std::make_move_iterator(epilogue_instrs.end()));
|
||||
}
|
||||
// 将尾声指令插入到 RET 指令之前
|
||||
mbb->getInstructions().insert(it,
|
||||
std::make_move_iterator(epilogue_instrs.begin()),
|
||||
std::make_move_iterator(epilogue_instrs.end()));
|
||||
|
||||
// 一个基本块通常只有一个终止指令,处理完就可以跳到下一个块
|
||||
goto next_block;
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,39 @@ std::string RISCv64CodeGen::code_gen() {
|
||||
return module_gen();
|
||||
}
|
||||
|
||||
unsigned RISCv64CodeGen::getTypeSizeInBytes(Type* type) {
|
||||
if (!type) {
|
||||
assert(false && "Cannot get size of a null type.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (type->getKind()) {
|
||||
// 对于SysY语言,基本类型int和float都占用4字节
|
||||
case Type::kInt:
|
||||
case Type::kFloat:
|
||||
return 4;
|
||||
|
||||
// 指针类型在RISC-V 64位架构下占用8字节
|
||||
// 虽然SysY没有'int*'语法,但数组变量在IR层面本身就是指针类型
|
||||
case Type::kPointer:
|
||||
return 8;
|
||||
|
||||
// 数组类型的总大小 = 元素数量 * 单个元素的大小
|
||||
case Type::kArray: {
|
||||
auto arrayType = type->as<ArrayType>();
|
||||
// 递归调用以计算元素大小
|
||||
return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType());
|
||||
}
|
||||
|
||||
// 其他类型,如Void, Label等不占用栈空间,或者不应该出现在这里
|
||||
default:
|
||||
// 如果遇到未处理的类型,触发断言,方便调试
|
||||
// assert(false && "Unsupported type for size calculation.");
|
||||
return 0; // 对于像Label或Void这样的类型,返回0是合理的
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printInitializer(std::stringstream& ss, const ValueCounter& init_values) {
|
||||
for (size_t i = 0; i < init_values.getValues().size(); ++i) {
|
||||
auto val = init_values.getValues()[i];
|
||||
@ -39,18 +72,36 @@ std::string RISCv64CodeGen::module_gen() {
|
||||
|
||||
for (const auto& global_ptr : module->getGlobals()) {
|
||||
GlobalValue* global = global_ptr.get();
|
||||
|
||||
// [核心修改] 使用更健壮的逻辑来判断是否为大型零初始化数组
|
||||
bool is_all_zeros = true;
|
||||
const auto& init_values = global->getInitValues();
|
||||
|
||||
// 判断是否为大型零初始化数组,以便放入.bss段
|
||||
bool is_large_zero_array = false;
|
||||
if (init_values.getValues().size() == 1) {
|
||||
if (auto const_val = dynamic_cast<ConstantValue*>(init_values.getValues()[0])) {
|
||||
if (const_val->isInt() && const_val->getInt() == 0 && init_values.getNumbers()[0] > 16) {
|
||||
is_large_zero_array = true;
|
||||
// 检查初始化值是否全部为0
|
||||
if (init_values.getValues().empty()) {
|
||||
// 如果 ValueCounter 为空,GlobalValue 的构造函数会确保它是零初始化的
|
||||
is_all_zeros = true;
|
||||
} else {
|
||||
for (auto val : init_values.getValues()) {
|
||||
if (auto const_val = dynamic_cast<ConstantValue*>(val)) {
|
||||
if (!const_val->isZero()) {
|
||||
is_all_zeros = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// 如果初始值包含非常量(例如,另一个全局变量的地址),则不认为是纯零初始化
|
||||
is_all_zeros = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 使用 getTypeSizeInBytes 检查总大小是否超过阈值 (16个整数 = 64字节)
|
||||
Type* allocated_type = global->getType()->as<PointerType>()->getBaseType();
|
||||
unsigned total_size = getTypeSizeInBytes(allocated_type);
|
||||
|
||||
bool is_large_zero_array = is_all_zeros && (total_size > 64);
|
||||
|
||||
if (is_large_zero_array) {
|
||||
bss_globals.push_back(global);
|
||||
} else {
|
||||
@ -58,12 +109,12 @@ std::string RISCv64CodeGen::module_gen() {
|
||||
}
|
||||
}
|
||||
|
||||
// --- 步骤2:生成 .bss 段的代码 (这部分不变) ---
|
||||
// --- 步骤2:生成 .bss 段的代码 ---
|
||||
if (!bss_globals.empty()) {
|
||||
ss << ".bss\n";
|
||||
for (GlobalValue* global : bss_globals) {
|
||||
unsigned count = global->getInitValues().getNumbers()[0];
|
||||
unsigned total_size = count * 4; // 假设元素都是4字节
|
||||
Type* allocated_type = global->getType()->as<PointerType>()->getBaseType();
|
||||
unsigned total_size = getTypeSizeInBytes(allocated_type);
|
||||
|
||||
ss << " .align 3\n";
|
||||
ss << ".globl " << global->getName() << "\n";
|
||||
@ -74,33 +125,45 @@ std::string RISCv64CodeGen::module_gen() {
|
||||
}
|
||||
}
|
||||
|
||||
// --- [修改] 步骤3:生成 .data 段的代码 ---
|
||||
// 我们需要检查 data_globals 和 常量列表是否都为空
|
||||
// --- 步骤3:生成 .data 段的代码 ---
|
||||
if (!data_globals.empty() || !module->getConsts().empty()) {
|
||||
ss << ".data\n";
|
||||
|
||||
// a. 先处理普通的全局变量 (GlobalValue)
|
||||
// a. 处理普通的全局变量 (GlobalValue)
|
||||
for (GlobalValue* global : data_globals) {
|
||||
Type* allocated_type = global->getType()->as<PointerType>()->getBaseType();
|
||||
unsigned total_size = getTypeSizeInBytes(allocated_type);
|
||||
|
||||
ss << " .align 3\n";
|
||||
ss << ".globl " << global->getName() << "\n";
|
||||
ss << ".type " << global->getName() << ", @object\n";
|
||||
ss << ".size " << global->getName() << ", " << total_size << "\n";
|
||||
ss << global->getName() << ":\n";
|
||||
printInitializer(ss, global->getInitValues());
|
||||
}
|
||||
|
||||
// b. [新增] 再处理全局常量 (ConstantVariable)
|
||||
// b. 处理全局常量 (ConstantVariable)
|
||||
for (const auto& const_ptr : module->getConsts()) {
|
||||
ConstantVariable* cnst = const_ptr.get();
|
||||
Type* allocated_type = cnst->getType()->as<PointerType>()->getBaseType();
|
||||
unsigned total_size = getTypeSizeInBytes(allocated_type);
|
||||
|
||||
ss << " .align 3\n";
|
||||
ss << ".globl " << cnst->getName() << "\n";
|
||||
ss << ".type " << cnst->getName() << ", @object\n";
|
||||
ss << ".size " << cnst->getName() << ", " << total_size << "\n";
|
||||
ss << cnst->getName() << ":\n";
|
||||
printInitializer(ss, cnst->getInitValues());
|
||||
}
|
||||
}
|
||||
|
||||
// --- 处理函数 (.text段) 的逻辑保持不变 ---
|
||||
// --- 步骤4:处理函数 (.text段) 的逻辑 ---
|
||||
if (!module->getFunctions().empty()) {
|
||||
ss << ".text\n";
|
||||
for (const auto& func_pair : module->getFunctions()) {
|
||||
if (func_pair.second.get()) {
|
||||
if (func_pair.second.get() && !func_pair.second->getBasicBlocks().empty()) {
|
||||
ss << function_gen(func_pair.second.get());
|
||||
if (DEBUG) std::cerr << "Function: " << func_pair.first << " generated.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -108,51 +171,222 @@ std::string RISCv64CodeGen::module_gen() {
|
||||
}
|
||||
|
||||
std::string RISCv64CodeGen::function_gen(Function* func) {
|
||||
// === 完整的后端处理流水线 ===
|
||||
if (DEBUG) {
|
||||
// === 完整的后端处理流水线 ===
|
||||
|
||||
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
|
||||
RISCv64ISel isel;
|
||||
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
|
||||
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
|
||||
DEBUG = 0;
|
||||
DEEPDEBUG = 0;
|
||||
|
||||
// 第一次调试打印输出
|
||||
std::stringstream ss1;
|
||||
RISCv64AsmPrinter printer1(mfunc.get());
|
||||
printer1.run(ss1, true);
|
||||
RISCv64ISel isel;
|
||||
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
|
||||
|
||||
// 阶段 2: 指令调度 (Instruction Scheduling)
|
||||
PreRA_Scheduler scheduler;
|
||||
scheduler.runOnMachineFunction(mfunc.get());
|
||||
// 第一次调试打印输出
|
||||
std::stringstream ss_after_isel;
|
||||
RISCv64AsmPrinter printer_isel(mfunc.get());
|
||||
printer_isel.run(ss_after_isel, true);
|
||||
// if (DEBUG) {
|
||||
// std::cout << ss_after_isel.str();
|
||||
// }
|
||||
DEBUG = 0;
|
||||
DEEPDEBUG = 0;
|
||||
DEBUG = 1;
|
||||
DEEPDEBUG = 1;
|
||||
if (DEBUG) {
|
||||
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
|
||||
<< ss_after_isel.str();
|
||||
}
|
||||
// DEBUG = 0;
|
||||
// DEEPDEBUG = 0;
|
||||
// [新增] 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
|
||||
// 这个Pass必须在寄存器分配之前运行
|
||||
EliminateFrameIndicesPass efi_pass;
|
||||
efi_pass.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
||||
RISCv64RegAlloc reg_alloc(mfunc.get());
|
||||
reg_alloc.run();
|
||||
if (DEBUG) {
|
||||
std::cerr << "====== stack info after eliminate frame indices ======\n";
|
||||
mfunc->dumpStackFrameInfo(std::cerr);
|
||||
// std::stringstream ss_after_eli;
|
||||
// printer_isel.run(ss_after_eli, true);
|
||||
// std::cerr << "====== LLIR after eliminate frame indices ======\n"
|
||||
// << ss_after_eli.str();
|
||||
}
|
||||
|
||||
// 阶段 3.1: 处理被调用者保存寄存器
|
||||
CalleeSavedHandler callee_handler;
|
||||
callee_handler.runOnMachineFunction(mfunc.get());
|
||||
// // 阶段 2: 指令调度 (Instruction Scheduling)
|
||||
// PreRA_Scheduler scheduler;
|
||||
// scheduler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 4: 窥孔优化 (Peephole Optimization)
|
||||
PeepholeOptimizer peephole;
|
||||
peephole.runOnMachineFunction(mfunc.get());
|
||||
// DEBUG = 0;
|
||||
// DEEPDEBUG = 0;
|
||||
// DEBUG = 1;
|
||||
// DEEPDEBUG = 1;
|
||||
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
||||
RISCv64RegAlloc reg_alloc(mfunc.get());
|
||||
reg_alloc.run();
|
||||
|
||||
// 阶段 5: 局部指令调度 (Local Scheduling)
|
||||
PostRA_Scheduler local_scheduler;
|
||||
local_scheduler.runOnMachineFunction(mfunc.get());
|
||||
// DEBUG = 0;
|
||||
// DEEPDEBUG = 0;
|
||||
DEBUG = 1;
|
||||
DEEPDEBUG = 1;
|
||||
if (DEBUG) {
|
||||
std::cerr << "====== stack info after reg alloc ======\n";
|
||||
mfunc->dumpStackFrameInfo(std::cerr);
|
||||
}
|
||||
|
||||
// 阶段 3.2: 插入序言和尾声
|
||||
PrologueEpilogueInsertionPass pei_pass;
|
||||
pei_pass.runOnMachineFunction(mfunc.get());
|
||||
// 阶段 3.1: 处理被调用者保存寄存器
|
||||
CalleeSavedHandler callee_handler;
|
||||
callee_handler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 3.3: 清理产生的大立即数
|
||||
LegalizeImmediatesPass legalizer;
|
||||
legalizer.runOnMachineFunction(mfunc.get());
|
||||
if (DEBUG) {
|
||||
std::cerr << "====== stack info after callee handler ======\n";
|
||||
mfunc->dumpStackFrameInfo(std::cerr);
|
||||
}
|
||||
|
||||
// 阶段 6: 代码发射 (Code Emission)
|
||||
std::stringstream ss;
|
||||
RISCv64AsmPrinter printer(mfunc.get());
|
||||
printer.run(ss);
|
||||
if (DEBUG) ss << "\n" << ss1.str(); // 将指令选择阶段的结果也包含在最终输出中
|
||||
return ss.str();
|
||||
// // 阶段 4: 窥孔优化 (Peephole Optimization)
|
||||
// PeepholeOptimizer peephole;
|
||||
// peephole.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 5: 局部指令调度 (Local Scheduling)
|
||||
// PostRA_Scheduler local_scheduler;
|
||||
// local_scheduler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 3.2: 插入序言和尾声
|
||||
PrologueEpilogueInsertionPass pei_pass;
|
||||
pei_pass.runOnMachineFunction(mfunc.get());
|
||||
|
||||
DEBUG = 0;
|
||||
DEEPDEBUG = 0;
|
||||
|
||||
// 阶段 3.3: 大立即数合法化
|
||||
LegalizeImmediatesPass legalizer;
|
||||
legalizer.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 6: 代码发射 (Code Emission)
|
||||
std::stringstream ss;
|
||||
RISCv64AsmPrinter printer(mfunc.get());
|
||||
printer.run(ss);
|
||||
|
||||
if (DEBUG) {
|
||||
ss << "\n\n; --- Intermediate Representation after Instruction Selection ---\n"
|
||||
<< ss_after_isel.str();
|
||||
}
|
||||
DEBUG = 1;
|
||||
DEEPDEBUG = 1;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
else {
|
||||
// === 完整的后端处理流水线 ===
|
||||
|
||||
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
|
||||
DEBUG = 0;
|
||||
DEEPDEBUG = 0;
|
||||
|
||||
RISCv64ISel isel;
|
||||
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
|
||||
|
||||
// 第一次调试打印输出
|
||||
std::stringstream ss_after_isel;
|
||||
RISCv64AsmPrinter printer_isel(mfunc.get());
|
||||
printer_isel.run(ss_after_isel, true);
|
||||
// if (DEBUG) {
|
||||
// std::cout << ss_after_isel.str();
|
||||
// }
|
||||
DEBUG = 0;
|
||||
DEEPDEBUG = 0;
|
||||
// DEBUG = 1;
|
||||
// DEEPDEBUG = 1;
|
||||
if (DEBUG) {
|
||||
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
|
||||
<< ss_after_isel.str();
|
||||
}
|
||||
// DEBUG = 0;
|
||||
// DEEPDEBUG = 0;
|
||||
// [新增] 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
|
||||
// 这个Pass必须在寄存器分配之前运行
|
||||
EliminateFrameIndicesPass efi_pass;
|
||||
efi_pass.runOnMachineFunction(mfunc.get());
|
||||
|
||||
if (DEBUG) {
|
||||
std::cerr << "====== stack info after eliminate frame indices ======\n";
|
||||
mfunc->dumpStackFrameInfo(std::cerr);
|
||||
std::stringstream ss_after_eli;
|
||||
printer_isel.run(ss_after_eli, true);
|
||||
std::cerr << "====== LLIR after eliminate frame indices ======\n"
|
||||
<< ss_after_eli.str();
|
||||
}
|
||||
|
||||
// // 阶段 2: 指令调度 (Instruction Scheduling)
|
||||
// PreRA_Scheduler scheduler;
|
||||
// scheduler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
DEBUG = 0;
|
||||
DEEPDEBUG = 0;
|
||||
// DEBUG = 1;
|
||||
// DEEPDEBUG = 1;
|
||||
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
||||
RISCv64RegAlloc reg_alloc(mfunc.get());
|
||||
reg_alloc.run();
|
||||
|
||||
DEBUG = 0;
|
||||
DEEPDEBUG = 0;
|
||||
// DEBUG = 1;
|
||||
// DEEPDEBUG = 1;
|
||||
if (DEBUG) {
|
||||
std::cerr << "====== stack info after reg alloc ======\n";
|
||||
mfunc->dumpStackFrameInfo(std::cerr);
|
||||
}
|
||||
|
||||
// 阶段 3.1: 处理被调用者保存寄存器
|
||||
CalleeSavedHandler callee_handler;
|
||||
callee_handler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
if (DEBUG) {
|
||||
std::cerr << "====== stack info after callee handler ======\n";
|
||||
mfunc->dumpStackFrameInfo(std::cerr);
|
||||
}
|
||||
|
||||
// // 阶段 4: 窥孔优化 (Peephole Optimization)
|
||||
// PeepholeOptimizer peephole;
|
||||
// peephole.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 5: 局部指令调度 (Local Scheduling)
|
||||
// PostRA_Scheduler local_scheduler;
|
||||
// local_scheduler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 3.2: 插入序言和尾声
|
||||
PrologueEpilogueInsertionPass pei_pass;
|
||||
pei_pass.runOnMachineFunction(mfunc.get());
|
||||
|
||||
DEBUG = 0;
|
||||
DEEPDEBUG = 0;
|
||||
|
||||
// 阶段 3.3: 大立即数合法化
|
||||
LegalizeImmediatesPass legalizer;
|
||||
legalizer.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 6: 代码发射 (Code Emission)
|
||||
std::stringstream ss;
|
||||
RISCv64AsmPrinter printer(mfunc.get());
|
||||
printer.run(ss);
|
||||
|
||||
if (DEBUG) {
|
||||
ss << "\n\n; --- Intermediate Representation after Instruction Selection ---\n"
|
||||
<< ss_after_isel.str();
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@ -1,6 +1,122 @@
|
||||
#include "RISCv64LLIR.h"
|
||||
#include <vector>
|
||||
#include <iostream> // 用于 std::ostream 和 std::cerr
|
||||
#include <string> // 用于 std::string
|
||||
|
||||
namespace sysy {
|
||||
|
||||
}
|
||||
// 辅助函数:将 PhysicalReg 枚举转换为可读的字符串
|
||||
std::string regToString(PhysicalReg reg) {
|
||||
switch (reg) {
|
||||
case PhysicalReg::ZERO: return "x0"; case PhysicalReg::RA: return "ra";
|
||||
case PhysicalReg::SP: return "sp"; case PhysicalReg::GP: return "gp";
|
||||
case PhysicalReg::TP: return "tp"; case PhysicalReg::T0: return "t0";
|
||||
case PhysicalReg::T1: return "t1"; case PhysicalReg::T2: return "t2";
|
||||
case PhysicalReg::S0: return "s0"; case PhysicalReg::S1: return "s1";
|
||||
case PhysicalReg::A0: return "a0"; case PhysicalReg::A1: return "a1";
|
||||
case PhysicalReg::A2: return "a2"; case PhysicalReg::A3: return "a3";
|
||||
case PhysicalReg::A4: return "a4"; case PhysicalReg::A5: return "a5";
|
||||
case PhysicalReg::A6: return "a6"; case PhysicalReg::A7: return "a7";
|
||||
case PhysicalReg::S2: return "s2"; case PhysicalReg::S3: return "s3";
|
||||
case PhysicalReg::S4: return "s4"; case PhysicalReg::S5: return "s5";
|
||||
case PhysicalReg::S6: return "s6"; case PhysicalReg::S7: return "s7";
|
||||
case PhysicalReg::S8: return "s8"; case PhysicalReg::S9: return "s9";
|
||||
case PhysicalReg::S10: return "s10"; case PhysicalReg::S11: return "s11";
|
||||
case PhysicalReg::T3: return "t3"; case PhysicalReg::T4: return "t4";
|
||||
case PhysicalReg::T5: return "t5"; case PhysicalReg::T6: return "t6";
|
||||
case PhysicalReg::F0: return "f0"; case PhysicalReg::F1: return "f1";
|
||||
case PhysicalReg::F2: return "f2"; case PhysicalReg::F3: return "f3";
|
||||
case PhysicalReg::F4: return "f4"; case PhysicalReg::F5: return "f5";
|
||||
case PhysicalReg::F6: return "f6"; case PhysicalReg::F7: return "f7";
|
||||
case PhysicalReg::F8: return "f8"; case PhysicalReg::F9: return "f9";
|
||||
case PhysicalReg::F10: return "f10"; case PhysicalReg::F11: return "f11";
|
||||
case PhysicalReg::F12: return "f12"; case PhysicalReg::F13: return "f13";
|
||||
case PhysicalReg::F14: return "f14"; case PhysicalReg::F15: return "f15";
|
||||
case PhysicalReg::F16: return "f16"; case PhysicalReg::F17: return "f17";
|
||||
case PhysicalReg::F18: return "f18"; case PhysicalReg::F19: return "f19";
|
||||
case PhysicalReg::F20: return "f20"; case PhysicalReg::F21: return "f21";
|
||||
case PhysicalReg::F22: return "f22"; case PhysicalReg::F23: return "f23";
|
||||
case PhysicalReg::F24: return "f24"; case PhysicalReg::F25: return "f25";
|
||||
case PhysicalReg::F26: return "f26"; case PhysicalReg::F27: return "f27";
|
||||
case PhysicalReg::F28: return "f28"; case PhysicalReg::F29: return "f29";
|
||||
case PhysicalReg::F30: return "f30"; case PhysicalReg::F31: return "f31";
|
||||
default: return "UNKNOWN_REG";
|
||||
}
|
||||
}
|
||||
|
||||
// [新增] 打印栈帧信息的完整实现
|
||||
void MachineFunction::dumpStackFrameInfo(std::ostream& os) const {
|
||||
const StackFrameInfo& info = frame_info;
|
||||
|
||||
os << "--- Stack Frame Info for function '" << getName() << "' ---\n";
|
||||
|
||||
// 打印尺寸信息
|
||||
os << " Sizes:\n";
|
||||
os << " Total Size: " << info.total_size << " bytes\n";
|
||||
os << " Locals Size: " << info.locals_size << " bytes\n";
|
||||
os << " Spill Size: " << info.spill_size << " bytes\n";
|
||||
os << " Callee-Saved Size: " << info.callee_saved_size << " bytes\n";
|
||||
os << "\n";
|
||||
|
||||
// 打印 Alloca 变量的偏移量
|
||||
os << " Alloca Offsets (vreg -> offset from FP):\n";
|
||||
if (info.alloca_offsets.empty()) {
|
||||
os << " (None)\n";
|
||||
} else {
|
||||
for (const auto& pair : info.alloca_offsets) {
|
||||
os << " %vreg" << pair.first << " -> " << pair.second << "\n";
|
||||
}
|
||||
}
|
||||
os << "\n";
|
||||
|
||||
// 打印溢出变量的偏移量
|
||||
os << " Spill Offsets (vreg -> offset from FP):\n";
|
||||
if (info.spill_offsets.empty()) {
|
||||
os << " (None)\n";
|
||||
} else {
|
||||
for (const auto& pair : info.spill_offsets) {
|
||||
os << " %vreg" << pair.first << " -> " << pair.second << "\n";
|
||||
}
|
||||
}
|
||||
os << "\n";
|
||||
|
||||
// 打印使用的被调用者保存寄存器
|
||||
os << " Used Callee-Saved Registers:\n";
|
||||
if (info.used_callee_saved_regs.empty()) {
|
||||
os << " (None)\n";
|
||||
} else {
|
||||
os << " { ";
|
||||
for (const auto& reg : info.used_callee_saved_regs) {
|
||||
os << regToString(reg) << " ";
|
||||
}
|
||||
os << "}\n";
|
||||
}
|
||||
os << "\n";
|
||||
|
||||
// 打印需要保存/恢复的被调用者保存寄存器 (有序)
|
||||
os << " Callee-Saved Registers to Store/Restore:\n";
|
||||
if (info.callee_saved_regs_to_store.empty()) {
|
||||
os << " (None)\n";
|
||||
} else {
|
||||
os << " [ ";
|
||||
for (const auto& reg : info.callee_saved_regs_to_store) {
|
||||
os << regToString(reg) << " ";
|
||||
}
|
||||
os << "]\n";
|
||||
}
|
||||
os << "\n";
|
||||
|
||||
// 打印最终的寄存器分配结果
|
||||
os << " Final Register Allocation Map (vreg -> preg):\n";
|
||||
if (info.vreg_to_preg_map.empty()) {
|
||||
os << " (None)\n";
|
||||
} else {
|
||||
for (const auto& pair : info.vreg_to_preg_map) {
|
||||
os << " %vreg" << pair.first << " -> " << regToString(pair.second) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
os << "---------------------------------------------------\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
20
src/include/backend/RISCv64/Handler/EliminateFrameIndices.h
Normal file
20
src/include/backend/RISCv64/Handler/EliminateFrameIndices.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef ELIMINATE_FRAME_INDICES_H
|
||||
#define ELIMINATE_FRAME_INDICES_H
|
||||
|
||||
#include "RISCv64LLIR.h"
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class EliminateFrameIndicesPass {
|
||||
public:
|
||||
// Pass 的主入口函数
|
||||
void runOnMachineFunction(MachineFunction* mfunc);
|
||||
|
||||
private:
|
||||
// 帮助计算类型大小的辅助函数,从原RegAlloc中移出
|
||||
unsigned getTypeSizeInBytes(Type* type);
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
#endif // ELIMINATE_FRAME_INDICES_H
|
||||
@ -22,6 +22,9 @@ private:
|
||||
// 函数级代码生成 (实现新的流水线)
|
||||
std::string function_gen(Function* func);
|
||||
|
||||
// 私有辅助函数,用于根据类型计算其占用的字节数。
|
||||
unsigned getTypeSizeInBytes(Type* type);
|
||||
|
||||
Module* module;
|
||||
};
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "IR.h" // 确保包含了您自己的IR头文件
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
@ -195,6 +196,11 @@ public:
|
||||
preg = new_preg;
|
||||
is_virtual = false;
|
||||
}
|
||||
|
||||
void setVRegNum(unsigned new_vreg_num) {
|
||||
vreg_num = new_vreg_num;
|
||||
is_virtual = true; // 确保设置vreg时,操作数状态正确
|
||||
}
|
||||
private:
|
||||
unsigned vreg_num = 0;
|
||||
PhysicalReg preg = PhysicalReg::ZERO;
|
||||
@ -280,8 +286,8 @@ struct StackFrameInfo {
|
||||
std::map<unsigned, int> alloca_offsets; // <AllocaInst的vreg, 栈偏移>
|
||||
std::map<unsigned, int> spill_offsets; // <溢出vreg, 栈偏移>
|
||||
std::set<PhysicalReg> used_callee_saved_regs; // 使用的保存寄存器
|
||||
std::map<unsigned, PhysicalReg> vreg_to_preg_map;
|
||||
std::vector<PhysicalReg> callee_saved_regs; // 用于存储需要保存的被调用者保存寄存器列表
|
||||
std::map<unsigned, PhysicalReg> vreg_to_preg_map; // [新增] RegAlloc最终的分配结果
|
||||
std::vector<PhysicalReg> callee_saved_regs_to_store; // [新增] 已排序的、需要存取的被调用者保存寄存器
|
||||
};
|
||||
|
||||
// 机器函数
|
||||
@ -295,7 +301,7 @@ public:
|
||||
StackFrameInfo& getFrameInfo() { return frame_info; }
|
||||
const std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() const { return blocks; }
|
||||
std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() { return blocks; }
|
||||
|
||||
void dumpStackFrameInfo(std::ostream& os = std::cerr) const;
|
||||
void addBlock(std::unique_ptr<MachineBasicBlock> block) {
|
||||
blocks.push_back(std::move(block));
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "CalleeSavedHandler.h"
|
||||
#include "LegalizeImmediates.h"
|
||||
#include "PrologueEpilogueInsertion.h"
|
||||
#include "EliminateFrameIndices.h"
|
||||
#include "Pass.h"
|
||||
|
||||
namespace sysy {
|
||||
|
||||
@ -3,9 +3,15 @@
|
||||
|
||||
#include "RISCv64LLIR.h"
|
||||
#include "RISCv64ISel.h" // 包含 RISCv64ISel.h 以访问 ISel 和 Value 类型
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
|
||||
extern int DEBUG;
|
||||
extern int DEEPDEBUG;
|
||||
extern int DEBUGLENGTH; // 用于限制调试输出的长度
|
||||
extern int DEEPERDEBUG; // 用于更深层次的调试输出
|
||||
|
||||
namespace sysy {
|
||||
|
||||
@ -17,58 +23,98 @@ public:
|
||||
void run();
|
||||
|
||||
private:
|
||||
using LiveSet = std::set<unsigned>; // 活跃虚拟寄存器集合
|
||||
using InterferenceGraph = std::map<unsigned, std::set<unsigned>>;
|
||||
// 类型定义,与Python版本对应
|
||||
using VRegSet = std::set<unsigned>;
|
||||
using InterferenceGraph = std::map<unsigned, VRegSet>;
|
||||
using VRegStack = std::vector<unsigned>; // 使用vector模拟栈,方便遍历
|
||||
using MoveList = std::map<unsigned, std::set<const MachineInstr*>>;
|
||||
using AliasMap = std::map<unsigned, unsigned>;
|
||||
using ColorMap = std::map<unsigned, PhysicalReg>;
|
||||
using VRegMoveSet = std::set<const MachineInstr*>;
|
||||
|
||||
// 栈帧管理
|
||||
void eliminateFrameIndices();
|
||||
|
||||
// 活跃性分析
|
||||
// --- 核心算法流程 ---
|
||||
void initialize();
|
||||
void build();
|
||||
void makeWorklist();
|
||||
void simplify();
|
||||
void coalesce();
|
||||
void freeze();
|
||||
void selectSpill();
|
||||
void assignColors();
|
||||
void rewriteProgram();
|
||||
bool doAllocation();
|
||||
void applyColoring();
|
||||
|
||||
void dumpState(const std::string &stage);
|
||||
|
||||
void precolorByCallingConvention();
|
||||
|
||||
// --- 辅助函数 ---
|
||||
void getInstrUseDef(const MachineInstr* instr, VRegSet& use, VRegSet& def);
|
||||
void getInstrUseDef_Liveness(const MachineInstr *instr, VRegSet &use, VRegSet &def);
|
||||
void addEdge(unsigned u, unsigned v);
|
||||
VRegSet adjacent(unsigned n);
|
||||
VRegMoveSet nodeMoves(unsigned n);
|
||||
bool moveRelated(unsigned n);
|
||||
void decrementDegree(unsigned m);
|
||||
void enableMoves(const VRegSet& nodes);
|
||||
unsigned getAlias(unsigned n);
|
||||
void addWorklist(unsigned u);
|
||||
bool briggsHeuristic(unsigned u, unsigned v);
|
||||
bool georgeHeuristic(unsigned u, unsigned v);
|
||||
void combine(unsigned u, unsigned v);
|
||||
void freezeMoves(unsigned u);
|
||||
void collectUsedCalleeSavedRegs();
|
||||
bool isFPVReg(unsigned vreg) const;
|
||||
std::string regToString(PhysicalReg reg);
|
||||
std::string regIdToString(unsigned id);
|
||||
|
||||
// --- 活跃性分析 ---
|
||||
void analyzeLiveness();
|
||||
|
||||
// 构建干扰图
|
||||
void buildInterferenceGraph();
|
||||
|
||||
// 图着色分配寄存器
|
||||
void colorGraph();
|
||||
|
||||
// 重写函数,替换vreg并插入溢出代码
|
||||
void rewriteFunction();
|
||||
|
||||
// 辅助函数,获取指令的Use/Def集合
|
||||
void getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def);
|
||||
|
||||
// 辅助函数,处理调用约定
|
||||
void handleCallingConvention();
|
||||
|
||||
MachineFunction* MFunc;
|
||||
|
||||
// 活跃性分析结果
|
||||
std::map<const MachineInstr*, LiveSet> live_in_map;
|
||||
std::map<const MachineInstr*, LiveSet> live_out_map;
|
||||
RISCv64ISel* ISel;
|
||||
|
||||
// 干扰图
|
||||
InterferenceGraph interference_graph;
|
||||
|
||||
// 图着色结果
|
||||
std::map<unsigned, PhysicalReg> color_map; // vreg -> preg
|
||||
std::set<unsigned> spilled_vregs; // 被溢出的vreg集合
|
||||
|
||||
// 可用的物理寄存器池
|
||||
// --- 算法数据结构 ---
|
||||
// 寄存器池
|
||||
std::vector<PhysicalReg> allocable_int_regs;
|
||||
std::vector<PhysicalReg> allocable_fp_regs;
|
||||
int K_int; // 整数寄存器数量
|
||||
int K_fp; // 浮点寄存器数量
|
||||
|
||||
// 存储vreg到IR Value*的反向映射
|
||||
// 这个map将在run()函数开始时被填充,并在rewriteFunction()中使用。
|
||||
std::map<unsigned, Value*> vreg_to_value_map;
|
||||
std::map<PhysicalReg, unsigned> preg_to_vreg_id_map; // 物理寄存器到特殊vreg ID的映射
|
||||
|
||||
// 用于计算类型大小的辅助函数
|
||||
unsigned getTypeSizeInBytes(Type* type);
|
||||
// 节点集合
|
||||
VRegSet precolored; // 预着色的节点 (物理寄存器)
|
||||
VRegSet initial; // 初始的、所有待处理的虚拟寄存器节点
|
||||
VRegSet simplifyWorklist;
|
||||
VRegSet freezeWorklist;
|
||||
VRegSet spillWorklist;
|
||||
VRegSet spilledNodes;
|
||||
VRegSet coalescedNodes;
|
||||
VRegSet coloredNodes;
|
||||
VRegStack selectStack;
|
||||
|
||||
// 辅助函数,用于打印集合
|
||||
static void printLiveSet(const LiveSet& s, const std::string& name, std::ostream& os);
|
||||
// Move指令相关
|
||||
std::set<const MachineInstr*> coalescedMoves;
|
||||
std::set<const MachineInstr*> constrainedMoves;
|
||||
std::set<const MachineInstr*> frozenMoves;
|
||||
std::set<const MachineInstr*> worklistMoves;
|
||||
std::set<const MachineInstr*> activeMoves;
|
||||
|
||||
// 数据结构
|
||||
InterferenceGraph adjSet;
|
||||
std::map<unsigned, VRegSet> adjList; // 邻接表
|
||||
std::map<unsigned, int> degree;
|
||||
MoveList moveList;
|
||||
AliasMap alias;
|
||||
ColorMap color_map;
|
||||
|
||||
// 活跃性分析结果
|
||||
std::map<const MachineInstr*, VRegSet> live_in_map;
|
||||
std::map<const MachineInstr*, VRegSet> live_out_map;
|
||||
|
||||
// VReg -> Value* 和 VReg -> Type* 的映射
|
||||
const std::map<unsigned, Value*>& vreg_to_value_map;
|
||||
const std::map<unsigned, Type*>& vreg_type_map;
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
@ -576,7 +576,9 @@ public:
|
||||
if (iter != predecessors.end()) {
|
||||
predecessors.erase(iter);
|
||||
} else {
|
||||
assert(false);
|
||||
// 如果没有找到前驱块,可能是因为它已经被移除或不存在
|
||||
// 这可能是一个错误情况,或者是因为在CFG优化过程中已经处理
|
||||
// assert(false && "Predecessor block not found in BasicBlock");
|
||||
}
|
||||
}
|
||||
void removeSuccessor(BasicBlock *block) {
|
||||
@ -584,7 +586,9 @@ public:
|
||||
if (iter != successors.end()) {
|
||||
successors.erase(iter);
|
||||
} else {
|
||||
assert(false);
|
||||
// 如果没有找到后继块,可能是因为它已经被移除或不存在
|
||||
// 这可能是一个错误情况,或者是因为在CFG优化过程中已经处理
|
||||
// assert(false && "Successor block not found in BasicBlock");
|
||||
}
|
||||
}
|
||||
void replacePredecessor(BasicBlock *oldBlock, BasicBlock *newBlock) {
|
||||
@ -916,10 +920,23 @@ class PhiInst : public Instruction {
|
||||
Value* getIncomingValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值
|
||||
BasicBlock* getIncomingBlock(unsigned k) const {return dynamic_cast<BasicBlock*>(getOperand(2 * k + 1));}
|
||||
|
||||
Value* getIncomingValue(BasicBlock* blk) const {
|
||||
return getvalfromBlk(blk);
|
||||
} ///< 获取指定基本块的传入值
|
||||
|
||||
BasicBlock* getIncomingBlock(Value* val) const {
|
||||
return getBlkfromVal(val);
|
||||
} ///< 获取指定值的传入基本块
|
||||
|
||||
void replaceIncoming(BasicBlock *oldBlock, BasicBlock *newBlock, Value *newValue){
|
||||
delBlk(oldBlock);
|
||||
addIncoming(newValue, newBlock);
|
||||
}
|
||||
|
||||
auto& getincomings() const {return blk2val;} ///< 获取所有的基本块和对应的值
|
||||
|
||||
Value* getvalfromBlk(BasicBlock* blk);
|
||||
BasicBlock* getBlkfromVal(Value* val);
|
||||
Value* getvalfromBlk(BasicBlock* blk) const ;
|
||||
BasicBlock* getBlkfromVal(Value* val) const ;
|
||||
|
||||
unsigned getNumIncomingValues() const { return vsize; } ///< 获取传入值的数量
|
||||
void addIncoming(Value *value, BasicBlock *block) {
|
||||
@ -930,6 +947,10 @@ class PhiInst : public Instruction {
|
||||
vsize++;
|
||||
} ///< 添加传入值和对应的基本块
|
||||
|
||||
void removeIncoming(BasicBlock *block){
|
||||
delBlk(block);
|
||||
}
|
||||
|
||||
void delValue(Value* val);
|
||||
void delBlk(BasicBlock* blk);
|
||||
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
#include "Pass.h"
|
||||
#include <queue>
|
||||
#include <set>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class BuildCFG : public OptimizationPass {
|
||||
public:
|
||||
static void *ID;
|
||||
BuildCFG() : OptimizationPass("BuildCFG", Granularity::Function) {}
|
||||
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
|
||||
void *getPassID() const override { return &ID; }
|
||||
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
@ -75,11 +75,7 @@ private:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
|
||||
// alloca: 当前正在处理的 AllocaInst
|
||||
// currentBB: 当前正在遍历的基本块
|
||||
// dt: 支配树分析结果
|
||||
// valueStack: 存储当前 AllocaInst 在当前路径上可见的 SSA 值栈
|
||||
void renameVariables(AllocaInst* alloca, BasicBlock* currentBB);
|
||||
void renameVariables(BasicBlock* currentBB);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 阶段4: 清理
|
||||
|
||||
@ -11,7 +11,6 @@ add_library(midend_lib STATIC
|
||||
Pass/Optimize/Reg2Mem.cpp
|
||||
Pass/Optimize/SysYIRCFGOpt.cpp
|
||||
Pass/Optimize/SCCP.cpp
|
||||
Pass/Optimize/BuildCFG.cpp
|
||||
)
|
||||
|
||||
# 包含中端模块所需的头文件路径
|
||||
|
||||
@ -569,15 +569,15 @@ void User::replaceOperand(unsigned index, Value *value) {
|
||||
* phi相关函数
|
||||
*/
|
||||
|
||||
Value* PhiInst::getvalfromBlk(BasicBlock* blk){
|
||||
refreshB2VMap();
|
||||
Value* PhiInst::getvalfromBlk(BasicBlock* blk) const {
|
||||
// refreshB2VMap();
|
||||
if( blk2val.find(blk) != blk2val.end()) {
|
||||
return blk2val.at(blk);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BasicBlock* PhiInst::getBlkfromVal(Value* val){
|
||||
BasicBlock* PhiInst::getBlkfromVal(Value* val) const {
|
||||
// 返回第一个值对应的基本块
|
||||
for(unsigned i = 0; i < vsize; i++) {
|
||||
if(getValue(i) == val) {
|
||||
@ -591,6 +591,9 @@ void PhiInst::delValue(Value* val){
|
||||
//根据value删除对应的基本块和值
|
||||
unsigned i = 0;
|
||||
BasicBlock* blk = getBlkfromVal(val);
|
||||
if(blk == nullptr) {
|
||||
return; // 如果val没有对应的基本块,直接返回
|
||||
}
|
||||
for(i = 0; i < vsize; i++) {
|
||||
if(getValue(i) == val) {
|
||||
break;
|
||||
@ -606,6 +609,9 @@ void PhiInst::delBlk(BasicBlock* blk){
|
||||
//根据Blk删除对应的基本块和值
|
||||
unsigned i = 0;
|
||||
Value* val = getvalfromBlk(blk);
|
||||
if(val == nullptr) {
|
||||
return; // 如果blk没有对应的值,直接返回
|
||||
}
|
||||
for(i = 0; i < vsize; i++) {
|
||||
if(getBlock(i) == blk) {
|
||||
break;
|
||||
@ -618,9 +624,12 @@ void PhiInst::delBlk(BasicBlock* blk){
|
||||
}
|
||||
|
||||
void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){
|
||||
refreshB2VMap();
|
||||
// refreshB2VMap();
|
||||
BasicBlock* oldBlk = getBlock(k);
|
||||
Value* val = blk2val.at(oldBlk);
|
||||
if(newBlk == oldBlk || oldBlk == nullptr) {
|
||||
return; // 如果新旧基本块相同,直接返回
|
||||
}
|
||||
// Value* val = blk2val.at(getBlock(k));
|
||||
// 替换基本块
|
||||
setOperand(2 * k + 1, newBlk);
|
||||
@ -630,7 +639,7 @@ void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){
|
||||
}
|
||||
|
||||
void PhiInst::replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk){
|
||||
refreshB2VMap();
|
||||
// refreshB2VMap();
|
||||
Value* val = blk2val.at(oldBlk);
|
||||
// 替换基本块
|
||||
delBlk(oldBlk);
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#include "Dom.h"
|
||||
#include <limits> // for std::numeric_limits
|
||||
#include <algorithm> // for std::set_intersection, std::set_difference, std::set_union
|
||||
#include <iostream> // for debug output
|
||||
#include <limits> // for std::numeric_limits
|
||||
#include <queue>
|
||||
|
||||
namespace sysy {
|
||||
@ -38,45 +40,80 @@ const std::set<BasicBlock *> *DominatorTree::getDominanceFrontier(BasicBlock *BB
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::set<BasicBlock*>* DominatorTree::getDominatorTreeChildren(BasicBlock* BB) const {
|
||||
auto it = DominatorTreeChildren.find(BB);
|
||||
if (it != DominatorTreeChildren.end()) {
|
||||
return &(it->second);
|
||||
}
|
||||
return nullptr;
|
||||
const std::set<BasicBlock *> *DominatorTree::getDominatorTreeChildren(BasicBlock *BB) const {
|
||||
auto it = DominatorTreeChildren.find(BB);
|
||||
if (it != DominatorTreeChildren.end()) {
|
||||
return &(it->second);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 辅助函数:打印 BasicBlock 集合
|
||||
void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) {
|
||||
if (!DEBUG)
|
||||
return;
|
||||
std::cout << prefix << "{";
|
||||
bool first = true;
|
||||
for (const auto &bb : s) {
|
||||
if (!first)
|
||||
std::cout << ", ";
|
||||
std::cout << bb->getName();
|
||||
first = false;
|
||||
}
|
||||
std::cout << "}" << std::endl;
|
||||
}
|
||||
|
||||
void DominatorTree::computeDominators(Function *F) {
|
||||
// 经典的迭代算法计算支配者集合
|
||||
// TODO: 可以替换为更高效的算法,如 Lengauer-Tarjan 算法
|
||||
BasicBlock *entryBlock = F->getEntryBlock();
|
||||
if (DEBUG)
|
||||
std::cout << "--- Computing Dominators ---" << std::endl;
|
||||
|
||||
BasicBlock *entryBlock = F->getEntryBlock();
|
||||
std::vector<BasicBlock *> bbs_in_order; // 用于确定遍历顺序,如果需要的话
|
||||
|
||||
// 初始化:入口块只被自己支配,其他块被所有块支配
|
||||
for (const auto &bb_ptr : F->getBasicBlocks()) {
|
||||
BasicBlock *bb = bb_ptr.get();
|
||||
bbs_in_order.push_back(bb); // 收集所有块
|
||||
if (bb == entryBlock) {
|
||||
Dominators[bb].insert(bb);
|
||||
if (DEBUG)
|
||||
std::cout << "Init Dominators[" << bb->getName() << "]: {" << bb->getName() << "}" << std::endl;
|
||||
} else {
|
||||
for (const auto &all_bb_ptr : F->getBasicBlocks()) {
|
||||
Dominators[bb].insert(all_bb_ptr.get());
|
||||
}
|
||||
if (DEBUG) {
|
||||
std::cout << "Init Dominators[" << bb->getName() << "]: ";
|
||||
printBBSet("", Dominators[bb]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool changed = true;
|
||||
int iteration = 0;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
for (const auto &bb_ptr : F->getBasicBlocks()) {
|
||||
iteration++;
|
||||
if (DEBUG)
|
||||
std::cout << "Iteration " << iteration << std::endl;
|
||||
|
||||
// 确保遍历顺序一致性,例如可以按照DFS或BFS顺序,或者简单的迭代器顺序
|
||||
// 如果Function::getBasicBlocks()返回的迭代器顺序稳定,则无需bbs_in_order
|
||||
for (const auto &bb_ptr : F->getBasicBlocks()) { // 假设这个迭代器顺序稳定
|
||||
BasicBlock *bb = bb_ptr.get();
|
||||
if (bb == entryBlock)
|
||||
continue;
|
||||
|
||||
// 计算所有前驱的支配者集合的交集
|
||||
std::set<BasicBlock *> newDom;
|
||||
bool firstPred = true;
|
||||
bool firstPredProcessed = false;
|
||||
|
||||
for (BasicBlock *pred : bb->getPredecessors()) {
|
||||
// 确保前驱的支配者集合已经计算过
|
||||
if (Dominators.count(pred)) {
|
||||
if (firstPred) {
|
||||
if (!firstPredProcessed) {
|
||||
newDom = Dominators[pred];
|
||||
firstPred = false;
|
||||
firstPredProcessed = true;
|
||||
} else {
|
||||
std::set<BasicBlock *> intersection;
|
||||
std::set_intersection(newDom.begin(), newDom.end(), Dominators[pred].begin(), Dominators[pred].end(),
|
||||
@ -85,21 +122,32 @@ void DominatorTree::computeDominators(Function *F) {
|
||||
}
|
||||
}
|
||||
}
|
||||
newDom.insert(bb);
|
||||
newDom.insert(bb); // BB 永远支配自己
|
||||
|
||||
if (newDom != Dominators[bb]) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Dominators[" << bb->getName() << "] changed from ";
|
||||
printBBSet("", Dominators[bb]);
|
||||
std::cout << " to ";
|
||||
printBBSet("", newDom);
|
||||
}
|
||||
Dominators[bb] = newDom;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DEBUG)
|
||||
std::cout << "--- Dominators Computation Finished ---" << std::endl;
|
||||
}
|
||||
|
||||
void DominatorTree::computeIDoms(Function *F) {
|
||||
// 采用与之前类似的简化实现。TODO:Lengauer-Tarjan等算法。
|
||||
BasicBlock *entryBlock = F->getEntryBlock();
|
||||
IDoms[entryBlock] = nullptr;
|
||||
if (DEBUG)
|
||||
std::cout << "--- Computing Immediate Dominators (IDoms) ---" << std::endl;
|
||||
|
||||
BasicBlock *entryBlock = F->getEntryBlock();
|
||||
IDoms[entryBlock] = nullptr; // 入口块没有即时支配者
|
||||
|
||||
// 遍历所有非入口块
|
||||
for (const auto &bb_ptr : F->getBasicBlocks()) {
|
||||
BasicBlock *bb = bb_ptr.get();
|
||||
if (bb == entryBlock)
|
||||
@ -107,91 +155,138 @@ void DominatorTree::computeIDoms(Function *F) {
|
||||
|
||||
BasicBlock *currentIDom = nullptr;
|
||||
const std::set<BasicBlock *> *domsOfBB = getDominators(bb);
|
||||
if (!domsOfBB)
|
||||
if (!domsOfBB) {
|
||||
if (DEBUG)
|
||||
std::cerr << "Warning: Dominators for " << bb->getName() << " not found!" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (BasicBlock *D : *domsOfBB) {
|
||||
if (D == bb)
|
||||
continue;
|
||||
// 遍历bb的所有严格支配者 D (即 bb 的支配者中除了 bb 自身)
|
||||
for (BasicBlock *D_candidate : *domsOfBB) {
|
||||
if (D_candidate == bb)
|
||||
continue; // 跳过bb自身
|
||||
|
||||
bool isCandidateIDom = true;
|
||||
for (BasicBlock *candidate : *domsOfBB) {
|
||||
if (candidate == bb || candidate == D)
|
||||
continue;
|
||||
const std::set<BasicBlock *> *domsOfCandidate = getDominators(candidate);
|
||||
if (domsOfCandidate && domsOfCandidate->count(D) == 0 && domsOfBB->count(candidate)) {
|
||||
isCandidateIDom = false;
|
||||
bool D_candidate_is_IDom = true;
|
||||
// 检查是否存在另一个块 X,使得 D_candidate 严格支配 X 且 X 严格支配 bb
|
||||
// 或者更直接的,检查 D_candidate 是否被 bb 的所有其他严格支配者所支配
|
||||
for (BasicBlock *X_other_dom : *domsOfBB) {
|
||||
if (X_other_dom == bb || X_other_dom == D_candidate)
|
||||
continue; // 跳过bb自身和D_candidate
|
||||
|
||||
// 如果 X_other_dom 严格支配 bb (它在 domsOfBB 中且不是bb自身)
|
||||
// 并且 X_other_dom 不被 D_candidate 支配,那么 D_candidate 就不是 IDom
|
||||
const std::set<BasicBlock *> *domsOfX_other_dom = getDominators(X_other_dom);
|
||||
if (domsOfX_other_dom && domsOfX_other_dom->count(D_candidate)) { // X_other_dom 支配 D_candidate
|
||||
// D_candidate 被另一个支配者 X_other_dom 支配
|
||||
// 这说明 D_candidate 位于 X_other_dom 的“下方”,X_other_dom 更接近 bb
|
||||
// 因此 D_candidate 不是 IDom
|
||||
D_candidate_is_IDom = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isCandidateIDom) {
|
||||
currentIDom = D;
|
||||
break;
|
||||
if (D_candidate_is_IDom) {
|
||||
currentIDom = D_candidate;
|
||||
break; // 找到即时支配者,可以退出循环,因为它是唯一的
|
||||
}
|
||||
}
|
||||
IDoms[bb] = currentIDom;
|
||||
if (DEBUG) {
|
||||
std::cout << " IDom[" << bb->getName() << "] = " << (currentIDom ? currentIDom->getName() : "nullptr")
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
if (DEBUG)
|
||||
std::cout << "--- Immediate Dominators Computation Finished ---" << std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
for each node n in a postorder traversal of the dominator tree:
|
||||
df[n] = empty set
|
||||
// compute DF_local(n)
|
||||
for each child y of n in the CFG:
|
||||
if idom[y] != n:
|
||||
df[n] = df[n] U {y}
|
||||
// compute DF_up(n)
|
||||
for each child c of n in the dominator tree:
|
||||
for each element w in df[c]:
|
||||
if idom[w] != n:
|
||||
df[n] = df[n] U {w}
|
||||
*/
|
||||
|
||||
void DominatorTree::computeDominanceFrontiers(Function *F) {
|
||||
// 经典的支配边界计算算法
|
||||
if (DEBUG)
|
||||
std::cout << "--- Computing Dominance Frontiers ---" << std::endl;
|
||||
|
||||
for (const auto &bb_ptr_X : F->getBasicBlocks()) {
|
||||
BasicBlock *X = bb_ptr_X.get();
|
||||
DominanceFrontiers[X].clear();
|
||||
|
||||
for (BasicBlock *Y : X->getSuccessors()) {
|
||||
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
|
||||
if (domsOfY && domsOfY->find(X) == domsOfY->end()) {
|
||||
DominanceFrontiers[X].insert(Y);
|
||||
}
|
||||
}
|
||||
|
||||
const std::set<BasicBlock *> *domsOfX = getDominators(X);
|
||||
if (!domsOfX)
|
||||
continue;
|
||||
// 遍历所有可能的 Z (X支配Z,或者Z就是X)
|
||||
for (const auto &bb_ptr_Z : F->getBasicBlocks()) {
|
||||
BasicBlock *Z = bb_ptr_Z.get();
|
||||
if (Z == X)
|
||||
continue;
|
||||
const std::set<BasicBlock *> *domsOfZ = getDominators(Z);
|
||||
if (domsOfZ && domsOfZ->count(X) && Z != X) {
|
||||
|
||||
for (BasicBlock *Y : Z->getSuccessors()) {
|
||||
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
|
||||
if (domsOfY && domsOfY->find(X) == domsOfY->end()) {
|
||||
DominanceFrontiers[X].insert(Y);
|
||||
}
|
||||
// 如果 X 不支配 Z,则 Z 与 DF(X) 无关
|
||||
if (!domsOfZ || domsOfZ->find(X) == domsOfZ->end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 遍历 Z 的所有后继 Y
|
||||
for (BasicBlock *Y : Z->getSuccessors()) {
|
||||
// 如果 Y 不被 X 严格支配,则 Y 在 DF(X) 中
|
||||
// Y 不被 X 严格支配意味着 (Y不被X支配) 或 (Y就是X)
|
||||
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
|
||||
if (Y == X || (domsOfY && domsOfY->find(X) == domsOfY->end())) {
|
||||
DominanceFrontiers[X].insert(Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
std::cout << " DF(" << X->getName() << "): ";
|
||||
printBBSet("", DominanceFrontiers[X]);
|
||||
}
|
||||
}
|
||||
if (DEBUG)
|
||||
std::cout << "--- Dominance Frontiers Computation Finished ---" << std::endl;
|
||||
}
|
||||
|
||||
void DominatorTree::computeDominatorTreeChildren(Function *F) {
|
||||
if (DEBUG)
|
||||
std::cout << "--- Computing Dominator Tree Children ---" << std::endl;
|
||||
// 首先清空,确保重新计算时是空的
|
||||
for (auto &bb_ptr : F->getBasicBlocks()) {
|
||||
DominatorTreeChildren[bb_ptr.get()].clear();
|
||||
}
|
||||
|
||||
for (auto &bb_ptr : F->getBasicBlocks()) {
|
||||
BasicBlock *B = bb_ptr.get();
|
||||
auto it = getImmediateDominator(B);
|
||||
if (it != nullptr) {
|
||||
BasicBlock *A = it;
|
||||
if (A) {
|
||||
DominatorTreeChildren[A].insert(B);
|
||||
BasicBlock *A = getImmediateDominator(B); // A 是 B 的即时支配者
|
||||
|
||||
if (A) { // 如果 B 有即时支配者 A (即 B 不是入口块)
|
||||
DominatorTreeChildren[A].insert(B);
|
||||
if (DEBUG) {
|
||||
std::cout << " " << B->getName() << " is child of " << A->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DEBUG)
|
||||
std::cout << "--- Dominator Tree Children Computation Finished ---" << std::endl;
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
// DominatorTreeAnalysisPass 的实现
|
||||
// ==============================================================
|
||||
|
||||
|
||||
bool DominatorTreeAnalysisPass::runOnFunction(Function* F, AnalysisManager &AM) {
|
||||
bool DominatorTreeAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
// 每次运行时清空旧数据,确保重新计算
|
||||
CurrentDominatorTree = std::make_unique<DominatorTree>(F);
|
||||
// 不需要手动清空map,unique_ptr会创建新的DominatorTree对象,其map是空的
|
||||
|
||||
CurrentDominatorTree->computeDominators(F);
|
||||
CurrentDominatorTree->computeIDoms(F);
|
||||
CurrentDominatorTree->computeIDoms(F); // 修正后的IDoms算法
|
||||
CurrentDominatorTree->computeDominanceFrontiers(F);
|
||||
CurrentDominatorTree->computeDominatorTreeChildren(F);
|
||||
return false;
|
||||
return false; // 分析遍通常返回 false,表示不修改 IR
|
||||
}
|
||||
|
||||
std::unique_ptr<AnalysisResultBase> DominatorTreeAnalysisPass::getResult() {
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
#include "BuildCFG.h"
|
||||
#include "Dom.h"
|
||||
#include "Liveness.h"
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
void *BuildCFG::ID = (void *)&BuildCFG::ID; // 定义唯一的 Pass ID
|
||||
|
||||
// 声明Pass的分析使用
|
||||
void BuildCFG::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
|
||||
// BuildCFG不依赖其他分析
|
||||
// analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 错误的例子
|
||||
|
||||
// BuildCFG会使所有依赖于CFG的分析结果失效,所以它必须声明这些失效
|
||||
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID);
|
||||
analysisInvalidations.insert(&LivenessAnalysisPass::ID);
|
||||
}
|
||||
|
||||
bool BuildCFG::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
if (DEBUG) {
|
||||
std::cout << "Running BuildCFG pass on function: " << F->getName() << std::endl;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
|
||||
// 1. 清空所有基本块的前驱和后继列表
|
||||
for (auto &bb : F->getBasicBlocks()) {
|
||||
bb->clearPredecessors();
|
||||
bb->clearSuccessors();
|
||||
}
|
||||
|
||||
// 2. 遍历每个基本块,重建CFG
|
||||
for (auto &bb : F->getBasicBlocks()) {
|
||||
// 获取基本块的最后一条指令
|
||||
auto &inst = *bb->terminator();
|
||||
Instruction *termInst = inst.get();
|
||||
// 确保基本块有终结指令
|
||||
if (!termInst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 根据终结指令类型,建立前驱后继关系
|
||||
if (termInst->isBranch()) {
|
||||
// 无条件跳转
|
||||
if (termInst->isUnconditional()) {
|
||||
auto brInst = dynamic_cast<UncondBrInst *>(termInst);
|
||||
BasicBlock *succ = dynamic_cast<BasicBlock *>(brInst->getBlock());
|
||||
assert(succ && "Branch instruction's target must be a BasicBlock");
|
||||
bb->addSuccessor(succ);
|
||||
succ->addPredecessor(bb.get());
|
||||
changed = true;
|
||||
|
||||
// 条件跳转
|
||||
} else if (termInst->isConditional()) {
|
||||
auto brInst = dynamic_cast<CondBrInst *>(termInst);
|
||||
BasicBlock *trueSucc = dynamic_cast<BasicBlock *>(brInst->getThenBlock());
|
||||
BasicBlock *falseSucc = dynamic_cast<BasicBlock *>(brInst->getElseBlock());
|
||||
|
||||
assert(trueSucc && falseSucc && "Branch instruction's targets must be BasicBlocks");
|
||||
|
||||
bb->addSuccessor(trueSucc);
|
||||
trueSucc->addPredecessor(bb.get());
|
||||
bb->addSuccessor(falseSucc);
|
||||
falseSucc->addPredecessor(bb.get());
|
||||
changed = true;
|
||||
}
|
||||
} else if (auto retInst = dynamic_cast<ReturnInst *>(termInst)) {
|
||||
// RetInst没有后继,无需处理
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@ -60,7 +60,7 @@ void Mem2RegContext::run(Function *func, AnalysisManager *AM) {
|
||||
}
|
||||
|
||||
// 从入口基本块开始,对支配树进行 DFS 遍历,进行变量重命名
|
||||
renameVariables(nullptr, func->getEntryBlock()); // 第一个参数 alloca 在这里不使用,因为是递归入口点
|
||||
renameVariables(func->getEntryBlock()); // 第一个参数 alloca 在这里不使用,因为是递归入口点
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 阶段4: 清理
|
||||
@ -209,16 +209,21 @@ void Mem2RegContext::insertPhis(AllocaInst *alloca, const std::unordered_set<Bas
|
||||
}
|
||||
|
||||
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
|
||||
void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *currentBB) {
|
||||
// 维护一个局部栈,用于存储当前基本块中为 Phi 和 Store 创建的 SSA 值,以便在退出时弹出
|
||||
std::stack<Value *> localStackPushed;
|
||||
// 移除了 AllocaInst *currentAlloca 参数,因为这个函数是为整个基本块处理所有可提升的 Alloca
|
||||
void Mem2RegContext::renameVariables(BasicBlock *currentBB) {
|
||||
// 1. 在函数开始时,记录每个 promotableAlloca 的当前栈深度。
|
||||
// 这将用于在函数返回时精确地回溯栈状态。
|
||||
std::map<AllocaInst *, size_t> originalStackSizes;
|
||||
for (auto alloca : promotableAllocas) {
|
||||
originalStackSizes[alloca] = allocaToValueStackMap[alloca].size();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 处理当前基本块的指令
|
||||
// --------------------------------------------------------------------
|
||||
for (auto instIter = currentBB->getInstructions().begin(); instIter != currentBB->getInstructions().end();) {
|
||||
Instruction *inst = instIter->get();
|
||||
bool instDeleted = false;
|
||||
bool instDeleted = false;
|
||||
|
||||
// 处理 Phi 指令 (如果是当前 alloca 的 Phi)
|
||||
if (auto phiInst = dynamic_cast<PhiInst *>(inst)) {
|
||||
@ -227,55 +232,69 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr
|
||||
if (allocaToPhiMap[alloca].count(currentBB) && allocaToPhiMap[alloca][currentBB] == phiInst) {
|
||||
// 为 Phi 指令的输出创建一个新的 SSA 值,并压入值栈
|
||||
allocaToValueStackMap[alloca].push(phiInst);
|
||||
localStackPushed.push(phiInst); // 记录以便弹出
|
||||
break; // 找到对应的 alloca,处理下一个指令
|
||||
if (DEBUG) {
|
||||
std::cout << "Mem2Reg: Pushed Phi " << (phiInst->getName().empty() ? "anonymous" : phiInst->getName()) << " for alloca " << alloca->getName()
|
||||
<< ". Stack size: " << allocaToValueStackMap[alloca].size() << std::endl;
|
||||
}
|
||||
break; // 找到对应的 alloca,处理下一个指令
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理 LoadInst
|
||||
else if (auto loadInst = dynamic_cast<LoadInst *>(inst)) {
|
||||
// 检查这个 LoadInst 是否是为某个可提升的 alloca
|
||||
for (auto alloca : promotableAllocas) {
|
||||
if (loadInst->getPointer() == alloca) {
|
||||
// loadInst->getPointer() 返回 AllocaInst*
|
||||
// 将 LoadInst 的所有用途替换为当前 alloca 值栈顶部的 SSA 值
|
||||
// 检查 LoadInst 的指针是否直接是 alloca,或者是指向 alloca 的 GEP
|
||||
Value *ptrOperand = loadInst->getPointer();
|
||||
if (ptrOperand == alloca || (dynamic_cast<GetElementPtrInst *>(ptrOperand) &&
|
||||
dynamic_cast<GetElementPtrInst *>(ptrOperand)->getBasePointer() == alloca)) {
|
||||
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca during load replacement!");
|
||||
if(DEBUG){
|
||||
std::cout << "Mem2Reg: Replacing load " << loadInst->getPointer()->getName() << " with SSA value." << std::endl;
|
||||
if (DEBUG) {
|
||||
std::cout << "Mem2Reg: Replacing load "
|
||||
<< (ptrOperand->getName().empty() ? "anonymous" : ptrOperand->getName()) << " with SSA value "
|
||||
<< (allocaToValueStackMap[alloca].top()->getName().empty()
|
||||
? "anonymous"
|
||||
: allocaToValueStackMap[alloca].top()->getName())
|
||||
<< " for alloca " << alloca->getName() << std::endl;
|
||||
std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName()
|
||||
<< "] size: " << allocaToValueStackMap[alloca].size() << std::endl;
|
||||
}
|
||||
loadInst->replaceAllUsesWith(allocaToValueStackMap[alloca].top());
|
||||
instIter = SysYIROptUtils::usedelete(instIter);
|
||||
instDeleted = true;
|
||||
// std::cerr << "Mem2Reg: Replaced load " << loadInst->name() << " with SSA value." << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理 StoreInst
|
||||
else if (auto storeInst = dynamic_cast<StoreInst *>(inst)) {
|
||||
// 检查这个 StoreInst 是否是为某个可提升的 alloca
|
||||
for (auto alloca : promotableAllocas) {
|
||||
if (storeInst->getPointer() == alloca) {
|
||||
// 假设 storeInst->getPointer() 返回 AllocaInst*
|
||||
// 将 StoreInst 存储的值作为新的 SSA 值,压入值栈
|
||||
if(DEBUG){
|
||||
std::cout << "Mem2Reg: Replacing store to " << storeInst->getPointer()->getName() << " with SSA value." << std::endl;
|
||||
// 检查 StoreInst 的指针是否直接是 alloca,或者是指向 alloca 的 GEP
|
||||
Value *ptrOperand = storeInst->getPointer();
|
||||
if (ptrOperand == alloca || (dynamic_cast<GetElementPtrInst *>(ptrOperand) &&
|
||||
dynamic_cast<GetElementPtrInst *>(ptrOperand)->getBasePointer() == alloca)) {
|
||||
if (DEBUG) {
|
||||
std::cout << "Mem2Reg: Replacing store to "
|
||||
<< (ptrOperand->getName().empty() ? "anonymous" : ptrOperand->getName()) << " with SSA value "
|
||||
<< (storeInst->getValue()->getName().empty() ? "anonymous" : storeInst->getValue()->getName())
|
||||
<< " for alloca " << alloca->getName() << std::endl;
|
||||
std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName()
|
||||
<< "] size before push: " << allocaToValueStackMap[alloca].size() << std::endl;
|
||||
}
|
||||
allocaToValueStackMap[alloca].push(storeInst->getValue());
|
||||
localStackPushed.push(storeInst->getValue()); // 记录以便弹出
|
||||
instIter = SysYIROptUtils::usedelete(instIter);
|
||||
instDeleted = true;
|
||||
// std::cerr << "Mem2Reg: Replaced store to " << storeInst->ptr()->name() << " with SSA value." << std::endl;
|
||||
if (DEBUG) {
|
||||
std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName()
|
||||
<< "] size after push: " << allocaToValueStackMap[alloca].size() << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!instDeleted) {
|
||||
++instIter; // 如果指令没有被删除,移动到下一个
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 处理后继基本块的 Phi 指令参数
|
||||
// --------------------------------------------------------------------
|
||||
@ -290,40 +309,57 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr
|
||||
// 参数值是当前 alloca 值栈顶部的 SSA 值
|
||||
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca when setting phi operand!");
|
||||
phiInst->addIncoming(allocaToValueStackMap[alloca].top(), currentBB);
|
||||
if (DEBUG) {
|
||||
std::cout << "Mem2Reg: Added incoming arg to Phi "
|
||||
<< (phiInst->getName().empty() ? "anonymous" : phiInst->getName()) << " from "
|
||||
<< currentBB->getName() << " with value "
|
||||
<< (allocaToValueStackMap[alloca].top()->getName().empty()
|
||||
? "anonymous"
|
||||
: allocaToValueStackMap[alloca].top()->getName())
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 递归访问支配树的子节点
|
||||
// --------------------------------------------------------------------
|
||||
const std::set<BasicBlock *> *dominatedBlocks = dt->getDominatorTreeChildren(currentBB);
|
||||
if(dominatedBlocks){
|
||||
if (dominatedBlocks) { // 检查是否存在子节点
|
||||
if(DEBUG){
|
||||
std::cout << "Mem2Reg: Processing dominated blocks for " << currentBB->getName() << std::endl;
|
||||
for (auto dominatedBB : *dominatedBlocks) {
|
||||
std::cout << "Mem2Reg: Dominated block: " << (dominatedBB ? dominatedBB->getName() : "null") << std::endl;
|
||||
}
|
||||
}
|
||||
for (auto dominatedBB : *dominatedBlocks) {
|
||||
if (dominatedBB) {
|
||||
if(DEBUG){
|
||||
std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() << std::endl;
|
||||
if (dominatedBB) { // 确保子块有效
|
||||
if (DEBUG) {
|
||||
std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName()
|
||||
<< std::endl;
|
||||
}
|
||||
renameVariables(currentAlloca, dominatedBB);
|
||||
renameVariables(dominatedBB); // 递归调用,不再传递 currentAlloca
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 退出基本块时,弹出在此块中压入值栈的 SSA 值
|
||||
// 退出基本块时,弹出在此块中压入值栈的 SSA 值,恢复栈到进入该块时的状态
|
||||
// --------------------------------------------------------------------
|
||||
while (!localStackPushed.empty()) {
|
||||
Value *val = localStackPushed.top();
|
||||
localStackPushed.pop();
|
||||
// 找到是哪个 alloca 对应的栈
|
||||
for (auto alloca : promotableAllocas) {
|
||||
if (!allocaToValueStackMap[alloca].empty() && allocaToValueStackMap[alloca].top() == val) {
|
||||
allocaToValueStackMap[alloca].pop();
|
||||
break;
|
||||
for (auto alloca : promotableAllocas) {
|
||||
while (allocaToValueStackMap[alloca].size() > originalStackSizes[alloca]) {
|
||||
if (DEBUG) {
|
||||
std::cout << "Mem2Reg: Popping value "
|
||||
<< (allocaToValueStackMap[alloca].top()->getName().empty()
|
||||
? "anonymous"
|
||||
: allocaToValueStackMap[alloca].top()->getName())
|
||||
<< " for alloca " << alloca->getName() << ". Stack size: " << allocaToValueStackMap[alloca].size()
|
||||
<< " -> " << (allocaToValueStackMap[alloca].size() - 1) << std::endl;
|
||||
}
|
||||
allocaToValueStackMap[alloca].pop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 删除所有原始的 AllocaInst、LoadInst 和 StoreInst
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
#include "SysYIRCFGOpt.h"
|
||||
#include "SysYIROptUtils.h"
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <queue> // 引入队列,SysYDelNoPreBLock需要
|
||||
#include <string>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
@ -18,7 +18,6 @@ void *SysYBlockMergePass::ID = (void *)&SysYBlockMergePass::ID;
|
||||
void *SysYAddReturnPass::ID = (void *)&SysYAddReturnPass::ID;
|
||||
void *SysYCondBr2BrPass::ID = (void *)&SysYCondBr2BrPass::ID;
|
||||
|
||||
|
||||
// ======================================================================
|
||||
// SysYCFGOptUtils: 辅助工具类,包含实际的CFG优化逻辑
|
||||
// ======================================================================
|
||||
@ -26,40 +25,42 @@ void *SysYCondBr2BrPass::ID = (void *)&SysYCondBr2BrPass::ID;
|
||||
// 删除br后的无用指令
|
||||
bool SysYCFGOptUtils::SysYDelInstAfterBr(Function *func) {
|
||||
bool changed = false;
|
||||
|
||||
|
||||
auto basicBlocks = func->getBasicBlocks();
|
||||
for (auto &basicBlock : basicBlocks) {
|
||||
bool Branch = false;
|
||||
auto &instructions = basicBlock->getInstructions();
|
||||
auto Branchiter = instructions.end();
|
||||
for (auto iter = instructions.begin(); iter != instructions.end(); ++iter) {
|
||||
if ((*iter)->isTerminator()){
|
||||
if ((*iter)->isTerminator()) {
|
||||
Branch = true;
|
||||
Branchiter = iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Branchiter != instructions.end()) ++Branchiter;
|
||||
if (Branchiter != instructions.end())
|
||||
++Branchiter;
|
||||
while (Branchiter != instructions.end()) {
|
||||
changed = true;
|
||||
Branchiter = instructions.erase(Branchiter);
|
||||
}
|
||||
|
||||
if (Branch) { // 更新前驱后继关系
|
||||
auto thelastinstinst = basicBlock->getInstructions().end();
|
||||
--thelastinstinst;
|
||||
|
||||
if (Branch) { // 更新前驱后继关系
|
||||
auto thelastinstinst = basicBlock->terminator();
|
||||
auto &Successors = basicBlock->getSuccessors();
|
||||
for (auto iterSucc = Successors.begin(); iterSucc != Successors.end();) {
|
||||
(*iterSucc)->removePredecessor(basicBlock.get());
|
||||
basicBlock->removeSuccessor(*iterSucc);
|
||||
}
|
||||
if (thelastinstinst->get()->isUnconditional()) {
|
||||
BasicBlock* branchBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(0));
|
||||
auto brinst = dynamic_cast<UncondBrInst *>(thelastinstinst->get());
|
||||
BasicBlock *branchBlock = dynamic_cast<BasicBlock *>(brinst->getBlock());
|
||||
basicBlock->addSuccessor(branchBlock);
|
||||
branchBlock->addPredecessor(basicBlock.get());
|
||||
} else if (thelastinstinst->get()->isConditional()) {
|
||||
BasicBlock* thenBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(1));
|
||||
BasicBlock* elseBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(2));
|
||||
auto brinst = dynamic_cast<CondBrInst *>(thelastinstinst->get());
|
||||
BasicBlock *thenBlock = dynamic_cast<BasicBlock *>(brinst->getThenBlock());
|
||||
BasicBlock *elseBlock = dynamic_cast<BasicBlock *>(brinst->getElseBlock());
|
||||
basicBlock->addSuccessor(thenBlock);
|
||||
basicBlock->addSuccessor(elseBlock);
|
||||
thenBlock->addPredecessor(basicBlock.get());
|
||||
@ -75,26 +76,26 @@ bool SysYCFGOptUtils::SysYDelInstAfterBr(Function *func) {
|
||||
bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
|
||||
bool changed = false;
|
||||
|
||||
for (auto blockiter = func->getBasicBlocks().begin();
|
||||
blockiter != func->getBasicBlocks().end();) {
|
||||
for (auto blockiter = func->getBasicBlocks().begin(); blockiter != func->getBasicBlocks().end();) {
|
||||
if (blockiter->get()->getNumSuccessors() == 1) {
|
||||
// 如果当前块只有一个后继块
|
||||
// 且后继块只有一个前驱块
|
||||
// 则将当前块和后继块合并
|
||||
if (((blockiter->get())->getSuccessors()[0])->getNumPredecessors() == 1) {
|
||||
// std::cout << "merge block: " << blockiter->get()->getName() << std::endl;
|
||||
BasicBlock* block = blockiter->get();
|
||||
BasicBlock* nextBlock = blockiter->get()->getSuccessors()[0];
|
||||
BasicBlock *block = blockiter->get();
|
||||
BasicBlock *nextBlock = blockiter->get()->getSuccessors()[0];
|
||||
// auto nextarguments = nextBlock->getArguments();
|
||||
// 删除br指令
|
||||
if (block->getNumInstructions() != 0) {
|
||||
auto thelastinstinst = block->end();
|
||||
(--thelastinstinst);
|
||||
auto thelastinstinst = block->terminator();
|
||||
if (thelastinstinst->get()->isUnconditional()) {
|
||||
thelastinstinst = SysYIROptUtils::usedelete(thelastinstinst);
|
||||
} else if (thelastinstinst->get()->isConditional()) {
|
||||
// 如果是条件分支,判断条件是否相同,主要优化相同布尔表达式
|
||||
if (thelastinstinst->get()->getOperand(1)->getName() == thelastinstinst->get()->getOperand(1)->getName()) {
|
||||
// 按道理不会走到这个分支
|
||||
// 如果是条件分支,查看then else是否相同
|
||||
auto brinst = dynamic_cast<CondBrInst *>(thelastinstinst->get());
|
||||
if (brinst->getThenBlock() == brinst->getElseBlock()) {
|
||||
thelastinstinst = SysYIROptUtils::usedelete(thelastinstinst);
|
||||
}
|
||||
}
|
||||
@ -104,7 +105,7 @@ bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
|
||||
for (auto institer = nextBlock->begin(); institer != nextBlock->end();) {
|
||||
institer->get()->setParent(block);
|
||||
block->getInstructions().emplace_back(institer->release());
|
||||
institer = nextBlock->getInstructions().erase(institer);
|
||||
institer = nextBlock->getInstructions().erase(institer);
|
||||
}
|
||||
// 更新前驱后继关系,类似树节点操作
|
||||
block->removeSuccessor(nextBlock);
|
||||
@ -135,318 +136,431 @@ bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
|
||||
|
||||
// 删除无前驱块,兼容SSA后的处理
|
||||
bool SysYCFGOptUtils::SysYDelNoPreBLock(Function *func) {
|
||||
|
||||
bool changed = false;
|
||||
bool changed = false; // 标记是否有基本块被删除
|
||||
std::set<BasicBlock *> reachableBlocks; // 用于存储所有可达的基本块
|
||||
std::queue<BasicBlock *> blockQueue; // BFS 遍历队列
|
||||
|
||||
for (auto &block : func->getBasicBlocks()) {
|
||||
block->setreachableFalse();
|
||||
BasicBlock *entryBlock = func->getEntryBlock();
|
||||
if (entryBlock) { // 确保函数有入口块
|
||||
reachableBlocks.insert(entryBlock); // 将入口块标记为可达
|
||||
blockQueue.push(entryBlock); // 入口块入队
|
||||
}
|
||||
// 对函数基本块做一个拓扑排序,排查不可达基本块
|
||||
auto entryBlock = func->getEntryBlock();
|
||||
entryBlock->setreachableTrue();
|
||||
std::queue<BasicBlock *> blockqueue;
|
||||
blockqueue.push(entryBlock);
|
||||
while (!blockqueue.empty()) {
|
||||
auto block = blockqueue.front();
|
||||
blockqueue.pop();
|
||||
for (auto &succ : block->getSuccessors()) {
|
||||
if (!succ->getreachable()) {
|
||||
succ->setreachableTrue();
|
||||
blockqueue.push(succ);
|
||||
// 如果没有入口块(比如一个空函数),则没有块是可达的,所有块都将被删除。
|
||||
|
||||
while (!blockQueue.empty()) { // BFS 遍历:只要队列不空
|
||||
BasicBlock *currentBlock = blockQueue.front();
|
||||
blockQueue.pop(); // 取出当前块
|
||||
|
||||
for (auto &succ : currentBlock->getSuccessors()) { // 遍历当前块的所有后继
|
||||
// 如果后继块不在 reachableBlocks 中(即尚未被访问过)
|
||||
if (reachableBlocks.find(succ) == reachableBlocks.end()) {
|
||||
reachableBlocks.insert(succ); // 标记为可达
|
||||
blockQueue.push(succ); // 入队,以便继续遍历
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除不可达基本块指令
|
||||
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end(); blockIter++) {
|
||||
if (!blockIter->get()->getreachable()) {
|
||||
for (auto instIter = blockIter->get()->getInstructions().begin();
|
||||
instIter != blockIter->get()->getInstructions().end();) {
|
||||
instIter = SysYIROptUtils::usedelete(instIter);
|
||||
std::vector<BasicBlock *> blocksToDelete; // 用于存储所有不可达的基本块
|
||||
|
||||
for (auto &blockPtr : func->getBasicBlocks()) {
|
||||
BasicBlock *block = blockPtr.get();
|
||||
// 如果当前块不在 reachableBlocks 集合中,说明它是不可达的
|
||||
if (reachableBlocks.find(block) == reachableBlocks.end()) {
|
||||
blocksToDelete.push_back(block); // 将其加入待删除列表
|
||||
changed = true; // 只要找到一个不可达块,就说明函数发生了改变
|
||||
}
|
||||
}
|
||||
|
||||
for (BasicBlock *unreachableBlock : blocksToDelete) {
|
||||
// 遍历不可达块中的所有指令,并删除它们
|
||||
for (auto instIter = unreachableBlock->getInstructions().begin();
|
||||
instIter != unreachableBlock->getInstructions().end();) {
|
||||
instIter = SysYIROptUtils::usedelete(instIter);
|
||||
}
|
||||
}
|
||||
|
||||
for (BasicBlock *unreachableBlock : blocksToDelete) {
|
||||
for (BasicBlock *succBlock : unreachableBlock->getSuccessors()) {
|
||||
// 只有当后继块自身是可达的(没有被删除)时才需要处理
|
||||
if (reachableBlocks.count(succBlock)) {
|
||||
for (auto &phiInstPtr : succBlock->getInstructions()) {
|
||||
// Phi 指令总是在基本块的开头。一旦遇到非 Phi 指令即可停止。
|
||||
if (phiInstPtr->getKind() != Instruction::kPhi) {
|
||||
break;
|
||||
}
|
||||
// 将这个 Phi 节点中来自不可达前驱(unreachableBlock)的输入参数删除
|
||||
dynamic_cast<PhiInst *>(phiInstPtr.get())->delBlk(unreachableBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
|
||||
if (!blockIter->get()->getreachable()) {
|
||||
for (auto succblock : blockIter->get()->getSuccessors()) {
|
||||
for (auto &phiinst : succblock->getInstructions()) {
|
||||
if (phiinst->getKind() != Instruction::kPhi) {
|
||||
break;
|
||||
}
|
||||
// 使用 delBlk 方法正确地删除对应于被删除基本块的传入值
|
||||
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(blockIter->get());
|
||||
}
|
||||
}
|
||||
// 删除不可达基本块,注意迭代器不可达问题
|
||||
BasicBlock *currentBlock = blockIter->get();
|
||||
// 如果当前块不在可达块集合中,则将其从函数中移除
|
||||
if (reachableBlocks.find(currentBlock) == reachableBlocks.end()) {
|
||||
// func->removeBasicBlock 应该返回下一个有效的迭代器
|
||||
func->removeBasicBlock((blockIter++)->get());
|
||||
changed = true;
|
||||
} else {
|
||||
blockIter++;
|
||||
blockIter++; // 如果可达,则移动到下一个块
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
// 删除空块
|
||||
bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) {
|
||||
bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
|
||||
bool changed = false;
|
||||
|
||||
// 收集不可达基本块
|
||||
// 这里的不可达基本块是指没有实际指令的基本块
|
||||
// 当一个基本块没有实际指令例如只有phi指令和一个uncondbr指令时,也会被视作不可达
|
||||
auto basicBlocks = func->getBasicBlocks();
|
||||
std::map<sysy::BasicBlock *, BasicBlock *> EmptyBlocks;
|
||||
// 空块儿和后继的基本块的映射
|
||||
for (auto &basicBlock : basicBlocks) {
|
||||
if (basicBlock->getNumInstructions() == 0) {
|
||||
if (basicBlock->getNumSuccessors() == 1) {
|
||||
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
|
||||
}
|
||||
}
|
||||
else{
|
||||
// 如果只有phi指令和一个uncondbr。(phi)*(uncondbr)?
|
||||
// 判断除了最后一个指令之外是不是只有phi指令
|
||||
bool onlyPhi = true;
|
||||
for (auto &inst : basicBlock->getInstructions()) {
|
||||
if (!inst->isPhi() && !inst->isUnconditional()) {
|
||||
onlyPhi = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(onlyPhi && basicBlock->getNumSuccessors() == 1) // 确保有后继且只有一个
|
||||
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
|
||||
}
|
||||
// 步骤 1: 识别并映射所有符合“空块”定义的基本块及其目标后继
|
||||
// 使用 std::map 来存储 <空块, 空块跳转目标>
|
||||
// 这样可以处理空块链:A -> B -> C,如果 B 是空块,A 应该跳到 C
|
||||
std::map<BasicBlock *, BasicBlock *> emptyBlockRedirectMap;
|
||||
|
||||
// 为了避免在遍历 func->getBasicBlocks() 时修改它导致迭代器失效,
|
||||
// 我们先收集所有的基本块。
|
||||
std::vector<BasicBlock *> allBlocks;
|
||||
for (auto &blockPtr : func->getBasicBlocks()) {
|
||||
allBlocks.push_back(blockPtr.get());
|
||||
}
|
||||
// 更新基本块信息,增加必要指令
|
||||
for (auto &basicBlock : basicBlocks) {
|
||||
// 把空块转换成只有跳转指令的不可达块 (这段逻辑在优化遍中可能需要调整,这里是原样保留)
|
||||
// 通常,DelEmptyBlock 应该在BlockMerge之后运行,如果存在完全空块,它会尝试填充一个Br指令。
|
||||
// 但是,它主要目的是重定向跳转。
|
||||
if (distance(basicBlock->begin(), basicBlock->end()) == 0) {
|
||||
if (basicBlock->getNumSuccessors() == 0) {
|
||||
continue;
|
||||
}
|
||||
if (basicBlock->getNumSuccessors() > 1) {
|
||||
// 如果一个空块有多个后继,说明CFG结构有问题或者需要特殊处理,这里简单assert
|
||||
assert(false && "Empty block with multiple successors found during SysYDelEmptyBlock");
|
||||
}
|
||||
// 这里的逻辑有点问题,如果一个块是空的,且只有一个后继,应该直接跳转到后继。
|
||||
// 如果这个块最终被删除了,那么其前驱也需要重定向。
|
||||
// 这个循环的目的是重定向现有的跳转指令,而不是创建新的。
|
||||
// 所以下面的逻辑才是核心。
|
||||
// pBuilder->setPosition(basicBlock.get(), basicBlock->end());
|
||||
// pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
|
||||
|
||||
for (BasicBlock *block : allBlocks) {
|
||||
// 入口块通常不应该被认为是空块并删除,除非它没有实际指令且只有一个后继,
|
||||
// 但为了安全起见,通常会跳过入口块的删除。
|
||||
// 如果入口块是空的,它应该被合并到它的后继,但处理起来更复杂,这里先不处理入口块为空的情况
|
||||
if (block == func->getEntryBlock()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto thelastinst = basicBlock->getInstructions().end();
|
||||
--thelastinst;
|
||||
|
||||
// 根据br指令传递的后继块信息,跳过空块链
|
||||
if (thelastinst->get()->isUnconditional()) {
|
||||
BasicBlock* OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
|
||||
BasicBlock *thelastBlockOld = nullptr;
|
||||
// 如果空块链表为多个块
|
||||
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)))) {
|
||||
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
|
||||
thelastinst->get()->replaceOperand(0, EmptyBlocks[thelastBlockOld]);
|
||||
}
|
||||
|
||||
// 如果有重定向发生
|
||||
if (thelastBlockOld != nullptr) {
|
||||
basicBlock->removeSuccessor(OldBrBlock);
|
||||
OldBrBlock->removePredecessor(basicBlock.get());
|
||||
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
|
||||
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
|
||||
changed = true; // 标记IR被修改
|
||||
}
|
||||
|
||||
|
||||
if (thelastBlockOld != nullptr) {
|
||||
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
|
||||
if (InstInNew->isPhi()) {
|
||||
// 使用 delBlk 方法删除 oldBlock 对应的传入值
|
||||
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
|
||||
} else {
|
||||
// 检查基本块是否是空的:除了Phi指令外,只包含一个终止指令 (Terminator)
|
||||
// 且该终止指令必须是无条件跳转。
|
||||
// 空块必须只有一个后继才能被简化
|
||||
if (block->getNumSuccessors() == 1) {
|
||||
bool hasNonPhiNonTerminator = false;
|
||||
// 遍历除了最后一个指令之外的指令
|
||||
for (auto instIter = block->getInstructions().begin(); instIter != block->getInstructions().end();) {
|
||||
// 如果是终止指令(例如 br, ret),且不是最后一个指令,则该块有问题
|
||||
if ((*instIter)->isTerminator() && instIter != block->terminator()) {
|
||||
hasNonPhiNonTerminator = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (thelastinst->get()->getKind() == Instruction::kCondBr) {
|
||||
auto OldThenBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
|
||||
auto OldElseBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
|
||||
bool thenChanged = false;
|
||||
bool elseChanged = false;
|
||||
|
||||
|
||||
BasicBlock *thelastBlockOld = nullptr;
|
||||
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)))) {
|
||||
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
|
||||
thelastinst->get()->replaceOperand(
|
||||
1, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))]);
|
||||
thenChanged = true;
|
||||
}
|
||||
|
||||
if (thenChanged) {
|
||||
basicBlock->removeSuccessor(OldThenBlock);
|
||||
OldThenBlock->removePredecessor(basicBlock.get());
|
||||
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)));
|
||||
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->addPredecessor(basicBlock.get());
|
||||
changed = true; // 标记IR被修改
|
||||
}
|
||||
|
||||
// 处理 then 和 else 分支合并的情况
|
||||
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
|
||||
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
|
||||
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
|
||||
thelastinst = SysYIROptUtils::usedelete(thelastinst);
|
||||
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
|
||||
pBuilder->createUncondBrInst(thebrBlock);
|
||||
changed = true; // 标记IR被修改
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thelastBlockOld != nullptr) {
|
||||
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->getInstructions()) {
|
||||
if (InstInNew->isPhi()) {
|
||||
// 使用 delBlk 方法删除 oldBlock 对应的传入值
|
||||
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
|
||||
} else {
|
||||
break;
|
||||
// 如果不是 Phi 指令且不是终止指令
|
||||
if (!(*instIter)->isPhi() && !(*instIter)->isTerminator()) {
|
||||
hasNonPhiNonTerminator = true;
|
||||
break;
|
||||
}
|
||||
++instIter;
|
||||
if (!hasNonPhiNonTerminator &&
|
||||
instIter == block->getInstructions().end()) { // 如果块中只有 Phi 指令和一个 Terminator
|
||||
// 确保最后一个指令是无条件跳转
|
||||
auto lastInst = block->terminator()->get();
|
||||
if (lastInst && lastInst->isUnconditional()) {
|
||||
emptyBlockRedirectMap[block] = block->getSuccessors().front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thelastBlockOld = nullptr;
|
||||
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2)))) {
|
||||
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
|
||||
thelastinst->get()->replaceOperand(
|
||||
2, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))]);
|
||||
elseChanged = true;
|
||||
}
|
||||
|
||||
if (elseChanged) {
|
||||
basicBlock->removeSuccessor(OldElseBlock);
|
||||
OldElseBlock->removePredecessor(basicBlock.get());
|
||||
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2)));
|
||||
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->addPredecessor(basicBlock.get());
|
||||
changed = true; // 标记IR被修改
|
||||
}
|
||||
|
||||
// 处理 then 和 else 分支合并的情况
|
||||
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
|
||||
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
|
||||
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
|
||||
thelastinst = SysYIROptUtils::usedelete(thelastinst);
|
||||
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
|
||||
pBuilder->createUncondBrInst(thebrBlock);
|
||||
changed = true; // 标记IR被修改
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// 如果有重定向发生
|
||||
// 需要更新后继块的前驱关系
|
||||
if (thelastBlockOld != nullptr) {
|
||||
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->getInstructions()) {
|
||||
if (InstInNew->isPhi()) {
|
||||
// 使用 delBlk 方法删除 oldBlock 对应的传入值
|
||||
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// 如果不是终止指令,但有后继 (例如,末尾没有显式终止指令的块)
|
||||
// 这段逻辑可能需要更严谨的CFG检查来确保正确性
|
||||
if (basicBlock->getNumSuccessors() == 1) {
|
||||
// 这里的逻辑似乎是想为没有terminator的块添加一个,但通常这应该在CFG构建阶段完成。
|
||||
// 如果这里仍然执行,确保它符合预期。
|
||||
// pBuilder->setPosition(basicBlock.get(), basicBlock->end());
|
||||
// pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
|
||||
// auto thelastinst = basicBlock->getInstructions().end();
|
||||
// (--thelastinst);
|
||||
// auto OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
|
||||
// sysy::BasicBlock *thelastBlockOld = nullptr;
|
||||
// while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))) !=
|
||||
// EmptyBlocks.end()) {
|
||||
// thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
|
||||
|
||||
// thelastinst->get()->replaceOperand(
|
||||
// 0, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))]);
|
||||
// }
|
||||
|
||||
// basicBlock->removeSuccessor(OldBrBlock);
|
||||
// OldBrBlock->removePredecessor(basicBlock.get());
|
||||
// basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
|
||||
// dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
|
||||
// changed = true; // 标记IR被修改
|
||||
// if (thelastBlockOld != nullptr) {
|
||||
// int indexphi = 0;
|
||||
// for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getPredecessors()) {
|
||||
// if (pred == thelastBlockOld) {
|
||||
// break;
|
||||
// }
|
||||
// indexphi++;
|
||||
// }
|
||||
|
||||
// for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
|
||||
// if (InstInNew->isPhi()) {
|
||||
// dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 真正的删除空块
|
||||
for (auto iter = func->getBasicBlocks().begin(); iter != func->getBasicBlocks().end();) {
|
||||
|
||||
if (EmptyBlocks.count(iter->get())) {
|
||||
// EntryBlock跳过
|
||||
if (iter->get() == func->getEntryBlock()) {
|
||||
++iter;
|
||||
continue;
|
||||
// 步骤 2: 遍历 emptyBlockRedirectMap,处理空块链
|
||||
// 确保每个空块都直接重定向到其最终的非空后继块
|
||||
for (auto const &[emptyBlock, directSucc] : emptyBlockRedirectMap) {
|
||||
BasicBlock *targetBlock = directSucc;
|
||||
// 沿着空块链一直找到最终的非空块目标
|
||||
while (emptyBlockRedirectMap.count(targetBlock)) {
|
||||
targetBlock = emptyBlockRedirectMap[targetBlock];
|
||||
}
|
||||
emptyBlockRedirectMap[emptyBlock] = targetBlock; // 更新映射到最终目标
|
||||
}
|
||||
|
||||
// 步骤 3: 遍历所有基本块,重定向其终止指令,绕过空块
|
||||
// 注意:这里需要再次遍历所有块,包括可能成为新目标的块
|
||||
for (BasicBlock *currentBlock : allBlocks) {
|
||||
// 如果 currentBlock 本身就是个空块,它会通过其前驱的重定向被处理,这里跳过
|
||||
if (emptyBlockRedirectMap.count(currentBlock)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取当前块的最后一个指令(终止指令)
|
||||
if (currentBlock->getInstructions().empty()) {
|
||||
// 理论上,除了入口块和可能被合并的空块外,所有块都应该有终止指令
|
||||
// 如果这里碰到空块,可能是逻辑错误或者需要特殊处理
|
||||
continue;
|
||||
}
|
||||
|
||||
std::function<Value *(Value *, BasicBlock *)> getUltimateSourceValue = [&](Value *val,
|
||||
BasicBlock *currentDefBlock) -> Value * {
|
||||
// 如果值不是指令,例如常量或函数参数,则它本身就是最终来源
|
||||
if (auto instr = dynamic_cast<Instruction *>(val)) { // Assuming Value* has a method to check if it's an instruction
|
||||
return val;
|
||||
}
|
||||
|
||||
for (auto instIter = iter->get()->getInstructions().begin();
|
||||
instIter != iter->get()->getInstructions().end();) {
|
||||
instIter = SysYIROptUtils::usedelete(instIter);
|
||||
Instruction *inst = dynamic_cast<Instruction *>(val);
|
||||
// 如果定义指令不在任何空块中,它就是最终来源
|
||||
if (!emptyBlockRedirectMap.count(currentDefBlock)) {
|
||||
return val;
|
||||
}
|
||||
// 删除不可达基本块的phi指令的操作数
|
||||
for (auto &succ : iter->get()->getSuccessors()) {
|
||||
for (auto &instinsucc : succ->getInstructions()) {
|
||||
if (instinsucc->isPhi()) {
|
||||
// iter->get() 就是当前被删除的空基本块,它作为前驱连接到这里的Phi指令
|
||||
dynamic_cast<PhiInst *>(instinsucc.get())->delBlk(iter->get());
|
||||
|
||||
// 如果是 Phi 指令,且它在空块中,则继续追溯其在空块链中前驱的传入值
|
||||
if (inst->getKind() == Instruction::kPhi) {
|
||||
PhiInst *phi = dynamic_cast<PhiInst *>(inst);
|
||||
// 查找哪个前驱是空块链中的上一个块
|
||||
for (size_t i = 0; i < phi->getNumOperands(); i += 2) {
|
||||
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phi->getOperand(i + 1));
|
||||
// 检查 incomingBlock 是否是当前空块的前驱,且也在空块映射中(或就是 P)
|
||||
// 找到在空块链中导致 currentDefBlock 的那个前驱块
|
||||
if (emptyBlockRedirectMap.count(incomingBlock) || incomingBlock == currentBlock) {
|
||||
// 递归追溯该传入值
|
||||
return getUltimateSourceValue(phi->getIncomingValue(incomingBlock), incomingBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果是其他指令或者无法追溯到Phi链,则认为它在空块中产生,无法安全传播,返回null或原值
|
||||
// 在严格的空块定义下,除了Phi和Terminator,不应有其他指令产生值。
|
||||
return val; // Fallback: If not a Phi, or unable to trace, return itself (may be dangling)
|
||||
};
|
||||
|
||||
auto lastInst = currentBlock->getInstructions().back().get();
|
||||
|
||||
if (lastInst->isUnconditional()) { // 无条件跳转
|
||||
UncondBrInst *brInst = dynamic_cast<UncondBrInst *>(lastInst);
|
||||
BasicBlock *oldTarget = dynamic_cast<BasicBlock *>(brInst->getBlock()); // 原始跳转目标
|
||||
|
||||
if (emptyBlockRedirectMap.count(oldTarget)) { // 如果目标是空块
|
||||
BasicBlock *newTarget = emptyBlockRedirectMap[oldTarget]; // 获取最终目标
|
||||
|
||||
// 更新 CFG 关系
|
||||
currentBlock->removeSuccessor(oldTarget);
|
||||
oldTarget->removePredecessor(currentBlock);
|
||||
|
||||
brInst->replaceOperand(0, newTarget); // 更新跳转指令的操作数
|
||||
currentBlock->addSuccessor(newTarget);
|
||||
newTarget->addPredecessor(currentBlock);
|
||||
|
||||
changed = true; // 标记发生改变
|
||||
|
||||
for (auto &phiInstPtr : newTarget->getInstructions()) {
|
||||
if (phiInstPtr->getKind() == Instruction::kPhi) {
|
||||
PhiInst *phiInst = dynamic_cast<PhiInst *>(phiInstPtr.get());
|
||||
BasicBlock *actualEmptyPredecessorOfS = nullptr;
|
||||
for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) {
|
||||
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phiInst->getOperand(i + 1));
|
||||
if (incomingBlock && emptyBlockRedirectMap.count(incomingBlock) &&
|
||||
emptyBlockRedirectMap[incomingBlock] == newTarget) {
|
||||
actualEmptyPredecessorOfS = incomingBlock;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (actualEmptyPredecessorOfS) {
|
||||
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
|
||||
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS);
|
||||
|
||||
// 追溯这个值,找到它在非空块中的最终来源
|
||||
// currentBlock 是 P
|
||||
// oldTarget 是 E1 (链的起点)
|
||||
// actualEmptyPredecessorOfS 是 En (链的终点,S 的前驱)
|
||||
Value *ultimateSourceValue = getUltimateSourceValue(valueFromEmptyPredecessor, actualEmptyPredecessorOfS);
|
||||
|
||||
// 替换 Phi 节点的传入块和传入值
|
||||
if (ultimateSourceValue) { // 确保成功追溯到有效来源
|
||||
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
|
||||
} else {
|
||||
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
|
||||
// 无法追溯到有效来源,这可能是个错误或特殊情况
|
||||
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值
|
||||
phiInst->removeIncoming(actualEmptyPredecessorOfS);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Phi 指令通常在基本块的开头,如果不是 Phi 指令就停止检查
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func->removeBasicBlock((iter++)->get());
|
||||
changed = true;
|
||||
} else {
|
||||
++iter;
|
||||
} else if (lastInst->getKind() == Instruction::kCondBr) { // 条件跳转
|
||||
CondBrInst *condBrInst = dynamic_cast<CondBrInst *>(lastInst);
|
||||
BasicBlock *oldThenTarget = dynamic_cast<BasicBlock *>(condBrInst->getThenBlock());
|
||||
BasicBlock *oldElseTarget = dynamic_cast<BasicBlock *>(condBrInst->getElseBlock());
|
||||
|
||||
bool thenPathChanged = false;
|
||||
bool elsePathChanged = false;
|
||||
|
||||
// 处理 Then 分支
|
||||
if (emptyBlockRedirectMap.count(oldThenTarget)) {
|
||||
BasicBlock *newThenTarget = emptyBlockRedirectMap[oldThenTarget];
|
||||
condBrInst->replaceOperand(1, newThenTarget); // 更新跳转指令操作数
|
||||
|
||||
currentBlock->removeSuccessor(oldThenTarget);
|
||||
oldThenTarget->removePredecessor(currentBlock);
|
||||
currentBlock->addSuccessor(newThenTarget);
|
||||
newThenTarget->addPredecessor(currentBlock);
|
||||
thenPathChanged = true;
|
||||
changed = true;
|
||||
|
||||
// 处理新 Then 目标块中的 Phi 指令
|
||||
// for (auto &phiInstPtr : newThenTarget->getInstructions()) {
|
||||
// if (phiInstPtr->getKind() == Instruction::kPhi) {
|
||||
// dynamic_cast<PhiInst *>(phiInstPtr.get())->delBlk(oldThenTarget);
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
for (auto &phiInstPtr : newThenTarget->getInstructions()) {
|
||||
if (phiInstPtr->getKind() == Instruction::kPhi) {
|
||||
PhiInst *phiInst = dynamic_cast<PhiInst *>(phiInstPtr.get());
|
||||
BasicBlock *actualEmptyPredecessorOfS = nullptr;
|
||||
for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) {
|
||||
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phiInst->getOperand(i + 1));
|
||||
if (incomingBlock && emptyBlockRedirectMap.count(incomingBlock) &&
|
||||
emptyBlockRedirectMap[incomingBlock] == newThenTarget) {
|
||||
actualEmptyPredecessorOfS = incomingBlock;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (actualEmptyPredecessorOfS) {
|
||||
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
|
||||
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS);
|
||||
|
||||
// 追溯这个值,找到它在非空块中的最终来源
|
||||
// currentBlock 是 P
|
||||
// oldTarget 是 E1 (链的起点)
|
||||
// actualEmptyPredecessorOfS 是 En (链的终点,S 的前驱)
|
||||
Value *ultimateSourceValue = getUltimateSourceValue(valueFromEmptyPredecessor, actualEmptyPredecessorOfS);
|
||||
|
||||
// 替换 Phi 节点的传入块和传入值
|
||||
if (ultimateSourceValue) { // 确保成功追溯到有效来源
|
||||
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
|
||||
} else {
|
||||
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
|
||||
// 无法追溯到有效来源,这可能是个错误或特殊情况
|
||||
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值
|
||||
phiInst->removeIncoming(actualEmptyPredecessorOfS);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 处理 Else 分支
|
||||
if (emptyBlockRedirectMap.count(oldElseTarget)) {
|
||||
BasicBlock *newElseTarget = emptyBlockRedirectMap[oldElseTarget];
|
||||
condBrInst->replaceOperand(2, newElseTarget); // 更新跳转指令操作数
|
||||
|
||||
currentBlock->removeSuccessor(oldElseTarget);
|
||||
oldElseTarget->removePredecessor(currentBlock);
|
||||
currentBlock->addSuccessor(newElseTarget);
|
||||
newElseTarget->addPredecessor(currentBlock);
|
||||
elsePathChanged = true;
|
||||
changed = true;
|
||||
|
||||
// 处理新 Else 目标块中的 Phi 指令
|
||||
// for (auto &phiInstPtr : newElseTarget->getInstructions()) {
|
||||
// if (phiInstPtr->getKind() == Instruction::kPhi) {
|
||||
// dynamic_cast<PhiInst *>(phiInstPtr.get())->delBlk(oldElseTarget);
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
for (auto &phiInstPtr : newElseTarget->getInstructions()) {
|
||||
if (phiInstPtr->getKind() == Instruction::kPhi) {
|
||||
PhiInst *phiInst = dynamic_cast<PhiInst *>(phiInstPtr.get());
|
||||
BasicBlock *actualEmptyPredecessorOfS = nullptr;
|
||||
for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) {
|
||||
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phiInst->getOperand(i + 1));
|
||||
if (incomingBlock && emptyBlockRedirectMap.count(incomingBlock) &&
|
||||
emptyBlockRedirectMap[incomingBlock] == newElseTarget) {
|
||||
actualEmptyPredecessorOfS = incomingBlock;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (actualEmptyPredecessorOfS) {
|
||||
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
|
||||
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS);
|
||||
|
||||
// 追溯这个值,找到它在非空块中的最终来源
|
||||
// currentBlock 是 P
|
||||
// oldTarget 是 E1 (链的起点)
|
||||
// actualEmptyPredecessorOfS 是 En (链的终点,S 的前驱)
|
||||
Value *ultimateSourceValue = getUltimateSourceValue(valueFromEmptyPredecessor, actualEmptyPredecessorOfS);
|
||||
|
||||
// 替换 Phi 节点的传入块和传入值
|
||||
if (ultimateSourceValue) { // 确保成功追溯到有效来源
|
||||
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
|
||||
} else {
|
||||
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
|
||||
// 无法追溯到有效来源,这可能是个错误或特殊情况
|
||||
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值
|
||||
phiInst->removeIncoming(actualEmptyPredecessorOfS);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 额外处理:如果条件跳转的两个分支现在指向同一个块,则可以简化为无条件跳转
|
||||
if (condBrInst->getThenBlock() == condBrInst->getElseBlock()) {
|
||||
BasicBlock *commonTarget = dynamic_cast<BasicBlock *>(condBrInst->getThenBlock());
|
||||
SysYIROptUtils::usedelete(lastInst); // 删除旧的条件跳转指令
|
||||
pBuilder->setPosition(currentBlock, currentBlock->end());
|
||||
pBuilder->createUncondBrInst(commonTarget); // 插入新的无条件跳转指令
|
||||
|
||||
// 更安全地更新 CFG 关系
|
||||
std::set<BasicBlock *> currentSuccessors;
|
||||
currentSuccessors.insert(oldThenTarget);
|
||||
currentSuccessors.insert(oldElseTarget);
|
||||
|
||||
// 移除旧的后继关系
|
||||
for (BasicBlock *succ : currentSuccessors) {
|
||||
currentBlock->removeSuccessor(succ);
|
||||
succ->removePredecessor(currentBlock);
|
||||
}
|
||||
// 添加新的后继关系
|
||||
currentBlock->addSuccessor(commonTarget);
|
||||
commonTarget->addPredecessor(currentBlock);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 步骤 4: 真正地删除空基本块
|
||||
// 注意:只能在所有跳转和 Phi 指令都更新完毕后才能删除这些块
|
||||
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
|
||||
BasicBlock *currentBlock = blockIter->get();
|
||||
if (emptyBlockRedirectMap.count(currentBlock)) { // 如果在空块映射中
|
||||
// 入口块不应该被删除,即使它符合空块定义,因为函数需要一个入口
|
||||
if (currentBlock == func->getEntryBlock()) {
|
||||
++blockIter;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 在删除块之前,确保其内部指令被正确删除(虽然这类块指令很少)
|
||||
for (auto instIter = currentBlock->getInstructions().begin();
|
||||
instIter != currentBlock->getInstructions().end();) {
|
||||
instIter = SysYIROptUtils::usedelete(instIter);
|
||||
}
|
||||
|
||||
// 移除块
|
||||
func->removeBasicBlock((blockIter++)->get());
|
||||
changed = true;
|
||||
} else {
|
||||
++blockIter;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
// 如果函数没有返回指令,则添加一个默认返回指令(主要解决void函数没有返回指令的问题)
|
||||
bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) {
|
||||
bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder *pBuilder) {
|
||||
bool changed = false;
|
||||
auto basicBlocks = func->getBasicBlocks();
|
||||
for (auto &block : basicBlocks) {
|
||||
@ -460,7 +574,8 @@ bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) {
|
||||
auto thelastinst = block->getInstructions().end();
|
||||
--thelastinst;
|
||||
if (thelastinst->get()->getKind() != Instruction::kReturn) {
|
||||
// std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default return." << std::endl;
|
||||
// std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default
|
||||
// return." << std::endl;
|
||||
|
||||
pBuilder->setPosition(block.get(), block->end());
|
||||
// TODO: 如果int float函数缺少返回值是否需要报错
|
||||
@ -476,7 +591,7 @@ bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@ -484,18 +599,18 @@ bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) {
|
||||
// 主要针对已知条件值的分支转换为无条件分支
|
||||
// 例如 if (cond) { ... } else { ... } 中的 cond 已经
|
||||
// 确定为 true 或 false 的情况
|
||||
bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
|
||||
bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder *pBuilder) {
|
||||
bool changed = false;
|
||||
|
||||
for (auto &basicblock : func->getBasicBlocks()) {
|
||||
if (basicblock->getNumInstructions() == 0)
|
||||
continue;
|
||||
|
||||
auto thelast = basicblock->getInstructions().end();
|
||||
--thelast;
|
||||
|
||||
if (thelast->get()->isConditional()){
|
||||
ConstantValue *constOperand = dynamic_cast<ConstantValue *>(thelast->get()->getOperand(0));
|
||||
auto thelast = basicblock->terminator();
|
||||
|
||||
if (thelast->get()->isConditional()) {
|
||||
auto condBrInst = dynamic_cast<CondBrInst *>(thelast->get());
|
||||
ConstantValue *constOperand = dynamic_cast<ConstantValue *>(condBrInst->getCondition());
|
||||
std::string opname;
|
||||
int constint = 0;
|
||||
float constfloat = 0.0F;
|
||||
@ -514,27 +629,27 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
|
||||
if (constfloat_Use || constint_Use) {
|
||||
changed = true;
|
||||
|
||||
auto thenBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(1));
|
||||
auto elseBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(2));
|
||||
auto thenBlock = dynamic_cast<BasicBlock *>(condBrInst->getThenBlock());
|
||||
auto elseBlock = dynamic_cast<BasicBlock *>(condBrInst->getElseBlock());
|
||||
thelast = SysYIROptUtils::usedelete(thelast);
|
||||
if ((constfloat_Use && constfloat == 1.0F) || (constint_Use && constint == 1)) {
|
||||
// cond为true或非0
|
||||
pBuilder->setPosition(basicblock.get(), basicblock->end());
|
||||
pBuilder->createUncondBrInst(thenBlock);
|
||||
|
||||
|
||||
// 更新CFG关系
|
||||
basicblock->removeSuccessor(elseBlock);
|
||||
elseBlock->removePredecessor(basicblock.get());
|
||||
|
||||
|
||||
// 删除elseBlock的phi指令中对应的basicblock.get()的传入值
|
||||
for (auto &phiinst : elseBlock->getInstructions()) {
|
||||
if (phiinst->getKind() != Instruction::kPhi) {
|
||||
break;
|
||||
}
|
||||
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
|
||||
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(basicblock.get());
|
||||
dynamic_cast<PhiInst *>(phiinst.get())->removeIncoming(basicblock.get());
|
||||
}
|
||||
|
||||
|
||||
} else { // cond为false或0
|
||||
|
||||
pBuilder->setPosition(basicblock.get(), basicblock->end());
|
||||
@ -550,9 +665,8 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
|
||||
break;
|
||||
}
|
||||
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
|
||||
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(basicblock.get());
|
||||
dynamic_cast<PhiInst *>(phiinst.get())->removeIncoming(basicblock.get());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -565,28 +679,28 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
|
||||
// 独立的CFG优化遍的实现
|
||||
// ======================================================================
|
||||
|
||||
bool SysYDelInstAfterBrPass::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||
bool SysYDelInstAfterBrPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
return SysYCFGOptUtils::SysYDelInstAfterBr(F);
|
||||
}
|
||||
|
||||
bool SysYDelEmptyBlockPass::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||
bool SysYDelEmptyBlockPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
return SysYCFGOptUtils::SysYDelEmptyBlock(F, pBuilder);
|
||||
}
|
||||
|
||||
bool SysYDelNoPreBLockPass::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||
bool SysYDelNoPreBLockPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
return SysYCFGOptUtils::SysYDelNoPreBLock(F);
|
||||
}
|
||||
|
||||
bool SysYBlockMergePass::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||
return SysYCFGOptUtils::SysYBlockMerge(F);
|
||||
bool SysYBlockMergePass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
return SysYCFGOptUtils::SysYBlockMerge(F);
|
||||
}
|
||||
|
||||
bool SysYAddReturnPass::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||
bool SysYAddReturnPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
return SysYCFGOptUtils::SysYAddReturn(F, pBuilder);
|
||||
}
|
||||
|
||||
bool SysYCondBr2BrPass::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||
bool SysYCondBr2BrPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
return SysYCFGOptUtils::SysYCondBr2Br(F, pBuilder);
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
} // namespace sysy
|
||||
@ -6,7 +6,6 @@
|
||||
#include "Mem2Reg.h"
|
||||
#include "Reg2Mem.h"
|
||||
#include "SCCP.h"
|
||||
#include "BuildCFG.h"
|
||||
#include "Pass.h"
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
@ -36,12 +35,10 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
||||
3. 添加优化passid
|
||||
*/
|
||||
// 注册分析遍
|
||||
registerAnalysisPass<DominatorTreeAnalysisPass>();
|
||||
registerAnalysisPass<LivenessAnalysisPass>();
|
||||
registerAnalysisPass<sysy::DominatorTreeAnalysisPass>();
|
||||
registerAnalysisPass<sysy::LivenessAnalysisPass>();
|
||||
|
||||
// 注册优化遍
|
||||
registerOptimizationPass<BuildCFG>();
|
||||
|
||||
registerOptimizationPass<SysYDelInstAfterBrPass>();
|
||||
registerOptimizationPass<SysYDelNoPreBLockPass>();
|
||||
registerOptimizationPass<SysYBlockMergePass>();
|
||||
@ -61,15 +58,6 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
||||
if (DEBUG) std::cout << "Applying -O1 optimizations.\n";
|
||||
if (DEBUG) std::cout << "--- Running custom optimization sequence ---\n";
|
||||
|
||||
if(DEBUG) {
|
||||
std::cout << "=== IR Before CFGOpt Optimizations ===\n";
|
||||
printPasses();
|
||||
}
|
||||
|
||||
this->clearPasses();
|
||||
this->addPass(&BuildCFG::ID);
|
||||
this->run();
|
||||
|
||||
this->clearPasses();
|
||||
this->addPass(&SysYDelInstAfterBrPass::ID);
|
||||
this->addPass(&SysYDelNoPreBLockPass::ID);
|
||||
|
||||
@ -653,7 +653,44 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx) {
|
||||
Value *currentValue = counterValues[k];
|
||||
unsigned currentRepeatNum = counterNumbers[k];
|
||||
|
||||
// 检查是否是0,并且重复次数足够大(例如 >16),才用 memset
|
||||
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(currentValue)) {
|
||||
if (constInt->getInt() == 0 && currentRepeatNum >= 16) { // 阈值可调整(如16、32等)
|
||||
// 计算 memset 的起始地址(基于当前线性偏移量)
|
||||
std::vector<Value *> memsetStartIndices;
|
||||
int tempLinearIndex = linearIndexOffset;
|
||||
|
||||
// 将线性索引转换为多维索引
|
||||
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) {
|
||||
memsetStartIndices.insert(memsetStartIndices.begin(),
|
||||
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
||||
tempLinearIndex /= dimSizes[dimIdx];
|
||||
}
|
||||
|
||||
// 构造 GEP 计算 memset 的起始地址
|
||||
std::vector<Value *> gepIndicesForMemset;
|
||||
gepIndicesForMemset.push_back(ConstantInteger::get(0)); // 跳过 alloca 类型
|
||||
gepIndicesForMemset.insert(gepIndicesForMemset.end(), memsetStartIndices.begin(),
|
||||
memsetStartIndices.end());
|
||||
|
||||
Value *memsetPtr = builder.createGetElementPtrInst(alloca, gepIndicesForMemset);
|
||||
|
||||
// 计算 memset 的字节数 = 元素个数 × 元素大小
|
||||
Type *elementType = type;;
|
||||
uint64_t elementSize = elementType->getSize();
|
||||
Value *size = ConstantInteger::get(currentRepeatNum * elementSize);
|
||||
|
||||
// 生成 memset 指令(假设你的 IRBuilder 有 createMemset 方法)
|
||||
builder.createMemsetInst(memsetPtr, ConstantInteger::get(0), size, ConstantInteger::get(0));
|
||||
|
||||
// 跳过这些已处理的0
|
||||
linearIndexOffset += currentRepeatNum;
|
||||
continue; // 直接进入下一次循环
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < currentRepeatNum; ++i) {
|
||||
// 对于非零值,生成对应的 store 指令
|
||||
std::vector<Value *> currentIndices;
|
||||
int tempLinearIndex = linearIndexOffset + i; // 使用偏移量和当前重复次数内的索引
|
||||
|
||||
@ -761,39 +798,73 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
|
||||
ConstantInteger::get(0));
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
int linearIndexOffset = 0; // 用于追踪当前处理的线性索引的偏移量
|
||||
for (int k = 0; k < counterValues.size(); ++k) {
|
||||
// 当前 Value 的值和重复次数
|
||||
Value* currentValue = counterValues[k];
|
||||
unsigned currentRepeatNum = counterNumbers[k];
|
||||
// 当前 Value 的值和重复次数
|
||||
Value *currentValue = counterValues[k];
|
||||
unsigned currentRepeatNum = counterNumbers[k];
|
||||
// 检查是否是0,并且重复次数足够大(例如 >16),才用 memset
|
||||
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(currentValue)) {
|
||||
if (constInt->getInt() == 0 && currentRepeatNum >= 16) { // 阈值可调整(如16、32等)
|
||||
// 计算 memset 的起始地址(基于当前线性偏移量)
|
||||
std::vector<Value *> memsetStartIndices;
|
||||
int tempLinearIndex = linearIndexOffset;
|
||||
|
||||
for (unsigned i = 0; i < currentRepeatNum; ++i) {
|
||||
std::vector<Value *> currentIndices;
|
||||
int tempLinearIndex = linearIndexOffset + i; // 使用偏移量和当前重复次数内的索引
|
||||
// 将线性索引转换为多维索引
|
||||
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) {
|
||||
memsetStartIndices.insert(memsetStartIndices.begin(),
|
||||
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
||||
tempLinearIndex /= dimSizes[dimIdx];
|
||||
}
|
||||
|
||||
// 将线性索引转换为多维索引
|
||||
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) {
|
||||
currentIndices.insert(currentIndices.begin(),
|
||||
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
||||
tempLinearIndex /= dimSizes[dimIdx];
|
||||
}
|
||||
|
||||
// 对于局部数组,alloca 本身就是 GEP 的基指针。
|
||||
// GEP 的第一个索引必须是 0,用于“步过”整个数组。
|
||||
std::vector<Value*> gepIndicesForInit;
|
||||
gepIndicesForInit.push_back(ConstantInteger::get(0));
|
||||
gepIndicesForInit.insert(gepIndicesForInit.end(), currentIndices.begin(), currentIndices.end());
|
||||
|
||||
// 计算元素的地址
|
||||
Value* elementAddress = getGEPAddressInst(alloca, gepIndicesForInit);
|
||||
// 生成 store 指令
|
||||
builder.createStoreInst(currentValue, elementAddress);
|
||||
// 构造 GEP 计算 memset 的起始地址
|
||||
std::vector<Value *> gepIndicesForMemset;
|
||||
gepIndicesForMemset.push_back(ConstantInteger::get(0)); // 跳过 alloca 类型
|
||||
gepIndicesForMemset.insert(gepIndicesForMemset.end(), memsetStartIndices.begin(),
|
||||
memsetStartIndices.end());
|
||||
|
||||
Value *memsetPtr = builder.createGetElementPtrInst(alloca, gepIndicesForMemset);
|
||||
|
||||
// 计算 memset 的字节数 = 元素个数 × 元素大小
|
||||
Type *elementType = type;
|
||||
;
|
||||
uint64_t elementSize = elementType->getSize();
|
||||
Value *size = ConstantInteger::get(currentRepeatNum * elementSize);
|
||||
|
||||
// 生成 memset 指令(假设你的 IRBuilder 有 createMemset 方法)
|
||||
builder.createMemsetInst(memsetPtr, ConstantInteger::get(0), size, ConstantInteger::get(0));
|
||||
|
||||
// 跳过这些已处理的0
|
||||
linearIndexOffset += currentRepeatNum;
|
||||
continue; // 直接进入下一次循环
|
||||
}
|
||||
// 更新线性索引偏移量,以便下一次迭代从正确的位置开始
|
||||
linearIndexOffset += currentRepeatNum;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < currentRepeatNum; ++i) {
|
||||
std::vector<Value *> currentIndices;
|
||||
int tempLinearIndex = linearIndexOffset + i; // 使用偏移量和当前重复次数内的索引
|
||||
|
||||
// 将线性索引转换为多维索引
|
||||
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) {
|
||||
currentIndices.insert(currentIndices.begin(),
|
||||
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
||||
tempLinearIndex /= dimSizes[dimIdx];
|
||||
}
|
||||
|
||||
// 对于局部数组,alloca 本身就是 GEP 的基指针。
|
||||
// GEP 的第一个索引必须是 0,用于“步过”整个数组。
|
||||
std::vector<Value *> gepIndicesForInit;
|
||||
gepIndicesForInit.push_back(ConstantInteger::get(0));
|
||||
gepIndicesForInit.insert(gepIndicesForInit.end(), currentIndices.begin(), currentIndices.end());
|
||||
|
||||
// 计算元素的地址
|
||||
Value *elementAddress = getGEPAddressInst(alloca, gepIndicesForInit);
|
||||
// 生成 store 指令
|
||||
builder.createStoreInst(currentValue, elementAddress);
|
||||
}
|
||||
// 更新线性索引偏移量,以便下一次迭代从正确的位置开始
|
||||
linearIndexOffset += currentRepeatNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -895,7 +966,7 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
|
||||
currentParamDims.push_back(ConstantInteger::get(-1)); // 标记第一个维度为未知
|
||||
for (const auto &exp : param->exp()) {
|
||||
// 访问表达式以获取维度大小,这些维度必须是常量
|
||||
Value* dimVal = std::any_cast<Value *>(visitExp(exp));
|
||||
Value* dimVal = computeExp(exp);
|
||||
// 确保维度是常量整数,否则 buildArrayType 会断言失败
|
||||
assert(dynamic_cast<ConstantInteger*>(dimVal) && "Array dimension in parameter must be a constant integer!");
|
||||
currentParamDims.push_back(dimVal);
|
||||
|
||||
@ -21,6 +21,8 @@ using namespace sysy;
|
||||
|
||||
int DEBUG = 0;
|
||||
int DEEPDEBUG = 0;
|
||||
int DEEPERDEBUG = 0;
|
||||
int DEBUGLENGTH = 50;
|
||||
|
||||
static string argStopAfter;
|
||||
static string argInputFile;
|
||||
|
||||
Reference in New Issue
Block a user