Compare commits
4 Commits
midend-m2r
...
backend-op
| Author | SHA1 | Date | |
|---|---|---|---|
| 5cf411680e | |||
| 33388496d5 | |||
| ef68235446 | |||
| 363ead0ddd |
Binary file not shown.
@ -103,7 +103,29 @@ void RISCv64ISel::select() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optLevel > 0) {
|
// 仅当函数满足特定条件时,才需要保存参数寄存器,应用更精细的过滤规则
|
||||||
|
// 1. 函数包含call指令 (非叶子函数): 参数寄存器(a0-a7)是调用者保存的,
|
||||||
|
// call指令可能会覆盖这些寄存器,因此必须保存。
|
||||||
|
// 2. 函数包含alloca指令 (需要栈分配)。
|
||||||
|
// 3. 函数的指令数量超过一个阈值(如20),意味着它是一个复杂的叶子函数,
|
||||||
|
// 为安全起见,保存其参数。
|
||||||
|
// 简单的叶子函数 (如min) 则可以跳过这个步骤进行优化。
|
||||||
|
auto shouldSaveArgs = [](Function* func) {
|
||||||
|
if (!func) return false;
|
||||||
|
int instruction_count = 0;
|
||||||
|
for (const auto& bb : func->getBasicBlocks()) {
|
||||||
|
for (const auto& inst : bb->getInstructions()) {
|
||||||
|
if (dynamic_cast<CallInst*>(inst.get()) || dynamic_cast<AllocaInst*>(inst.get())) {
|
||||||
|
return true; // 发现call或alloca,立即返回true
|
||||||
|
}
|
||||||
|
instruction_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果没有call或alloca,则检查指令数量
|
||||||
|
return instruction_count > 45;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (optLevel > 0 && shouldSaveArgs(F)) {
|
||||||
if (F && !F->getBasicBlocks().empty()) {
|
if (F && !F->getBasicBlocks().empty()) {
|
||||||
// 定位到第一个MachineBasicBlock,也就是函数入口
|
// 定位到第一个MachineBasicBlock,也就是函数入口
|
||||||
BasicBlock* first_ir_block = F->getBasicBlocks_NoRange().front().get();
|
BasicBlock* first_ir_block = F->getBasicBlocks_NoRange().front().get();
|
||||||
@ -1311,6 +1333,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
auto gep = dynamic_cast<GetElementPtrInst*>(node->value);
|
auto gep = dynamic_cast<GetElementPtrInst*>(node->value);
|
||||||
auto result_vreg = getVReg(gep);
|
auto result_vreg = getVReg(gep);
|
||||||
|
|
||||||
|
if (optLevel == 0) {
|
||||||
// --- Step 1: 获取基地址 (此部分逻辑正确,保持不变) ---
|
// --- Step 1: 获取基地址 (此部分逻辑正确,保持不变) ---
|
||||||
auto base_ptr_node = node->operands[0];
|
auto base_ptr_node = node->operands[0];
|
||||||
auto current_addr_vreg = getNewVReg(gep->getType());
|
auto current_addr_vreg = getNewVReg(gep->getType());
|
||||||
@ -1417,6 +1440,106 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
final_mv->addOperand(std::make_unique<RegOperand>(current_addr_vreg));
|
final_mv->addOperand(std::make_unique<RegOperand>(current_addr_vreg));
|
||||||
CurMBB->addInstruction(std::move(final_mv));
|
CurMBB->addInstruction(std::move(final_mv));
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
// 对于-O1时的处理逻辑
|
||||||
|
// --- Step 1: 获取基地址 ---
|
||||||
|
auto base_ptr_node = node->operands[0];
|
||||||
|
auto base_ptr_val = base_ptr_node->value;
|
||||||
|
|
||||||
|
// last_step_addr_vreg 保存上一步计算的结果。
|
||||||
|
// 它首先被初始化为GEP的初始基地址。
|
||||||
|
unsigned last_step_addr_vreg;
|
||||||
|
|
||||||
|
if (auto alloca_base = dynamic_cast<AllocaInst*>(base_ptr_val)) {
|
||||||
|
last_step_addr_vreg = getNewVReg(gep->getType());
|
||||||
|
auto frame_addr_instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR);
|
||||||
|
frame_addr_instr->addOperand(std::make_unique<RegOperand>(last_step_addr_vreg));
|
||||||
|
frame_addr_instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca_base)));
|
||||||
|
CurMBB->addInstruction(std::move(frame_addr_instr));
|
||||||
|
} else if (auto global_base = dynamic_cast<GlobalValue*>(base_ptr_val)) {
|
||||||
|
last_step_addr_vreg = getNewVReg(gep->getType());
|
||||||
|
auto la_instr = std::make_unique<MachineInstr>(RVOpcodes::LA);
|
||||||
|
la_instr->addOperand(std::make_unique<RegOperand>(last_step_addr_vreg));
|
||||||
|
la_instr->addOperand(std::make_unique<LabelOperand>(global_base->getName()));
|
||||||
|
CurMBB->addInstruction(std::move(la_instr));
|
||||||
|
} else {
|
||||||
|
// 对于函数参数或来自其他指令的指针,直接获取其vreg。
|
||||||
|
// 这个vreg必须被保护,不能在计算中被修改。
|
||||||
|
last_step_addr_vreg = getVReg(base_ptr_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Step 2: 遵循LLVM GEP语义迭代计算地址 ---
|
||||||
|
Type* current_type = gep->getBasePointer()->getType()->as<PointerType>()->getBaseType();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < gep->getNumIndices(); ++i) {
|
||||||
|
Value* indexValue = gep->getIndex(i);
|
||||||
|
unsigned stride = getTypeSizeInBytes(current_type);
|
||||||
|
|
||||||
|
if (stride != 0) {
|
||||||
|
// --- 为当前索引和步长生成偏移计算指令 ---
|
||||||
|
auto offset_vreg = getNewVReg(Type::getIntType());
|
||||||
|
|
||||||
|
unsigned index_vreg;
|
||||||
|
if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) {
|
||||||
|
index_vreg = getNewVReg(Type::getIntType());
|
||||||
|
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||||
|
li->addOperand(std::make_unique<RegOperand>(index_vreg));
|
||||||
|
li->addOperand(std::make_unique<ImmOperand>(const_index->getInt()));
|
||||||
|
CurMBB->addInstruction(std::move(li));
|
||||||
|
} else {
|
||||||
|
index_vreg = getVReg(indexValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stride == 1) {
|
||||||
|
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
||||||
|
mv->addOperand(std::make_unique<RegOperand>(offset_vreg));
|
||||||
|
mv->addOperand(std::make_unique<RegOperand>(index_vreg));
|
||||||
|
CurMBB->addInstruction(std::move(mv));
|
||||||
|
} else {
|
||||||
|
auto size_vreg = getNewVReg(Type::getIntType());
|
||||||
|
auto li_size = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||||
|
li_size->addOperand(std::make_unique<RegOperand>(size_vreg));
|
||||||
|
li_size->addOperand(std::make_unique<ImmOperand>(stride));
|
||||||
|
CurMBB->addInstruction(std::move(li_size));
|
||||||
|
|
||||||
|
auto mul = std::make_unique<MachineInstr>(RVOpcodes::MULW);
|
||||||
|
mul->addOperand(std::make_unique<RegOperand>(offset_vreg));
|
||||||
|
mul->addOperand(std::make_unique<RegOperand>(index_vreg));
|
||||||
|
mul->addOperand(std::make_unique<RegOperand>(size_vreg));
|
||||||
|
CurMBB->addInstruction(std::move(mul));
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 关键修复点 ---
|
||||||
|
// 创建一个新的vreg来保存本次加法的结果。
|
||||||
|
unsigned current_step_addr_vreg = getNewVReg(gep->getType());
|
||||||
|
|
||||||
|
// 执行 add current_step, last_step, offset
|
||||||
|
// 这确保了 last_step_addr_vreg (输入) 永远不会被直接修改。
|
||||||
|
auto add = std::make_unique<MachineInstr>(RVOpcodes::ADD);
|
||||||
|
add->addOperand(std::make_unique<RegOperand>(current_step_addr_vreg));
|
||||||
|
add->addOperand(std::make_unique<RegOperand>(last_step_addr_vreg));
|
||||||
|
add->addOperand(std::make_unique<RegOperand>(offset_vreg));
|
||||||
|
CurMBB->addInstruction(std::move(add));
|
||||||
|
|
||||||
|
// 本次的结果成为下一次计算的输入。
|
||||||
|
last_step_addr_vreg = current_step_addr_vreg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 为下一次迭代更新类型 ---
|
||||||
|
if (auto array_type = current_type->as<ArrayType>()) {
|
||||||
|
current_type = array_type->getElementType();
|
||||||
|
} else if (auto ptr_type = current_type->as<PointerType>()) {
|
||||||
|
current_type = ptr_type->getBaseType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Step 3: 将最终计算出的地址存入GEP的目标虚拟寄存器 ---
|
||||||
|
auto final_mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
||||||
|
final_mv->addOperand(std::make_unique<RegOperand>(result_vreg));
|
||||||
|
final_mv->addOperand(std::make_unique<RegOperand>(last_step_addr_vreg));
|
||||||
|
CurMBB->addInstruction(std::move(final_mv));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -51,6 +51,7 @@ public:
|
|||||||
Module *pModule, IRBuilder *pBuilder);
|
Module *pModule, IRBuilder *pBuilder);
|
||||||
|
|
||||||
static void initExternalFunction(Module *pModule, IRBuilder *pBuilder);
|
static void initExternalFunction(Module *pModule, IRBuilder *pBuilder);
|
||||||
|
static void modify_timefuncname(Module *pModule);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SysYIRGenerator : public SysYBaseVisitor {
|
class SysYIRGenerator : public SysYBaseVisitor {
|
||||||
|
|||||||
@ -674,6 +674,8 @@ std::any SysYIRGenerator::visitCompUnit(SysYParser::CompUnitContext *ctx) {
|
|||||||
pModule->enterNewScope();
|
pModule->enterNewScope();
|
||||||
visitChildren(ctx);
|
visitChildren(ctx);
|
||||||
pModule->leaveScope();
|
pModule->leaveScope();
|
||||||
|
|
||||||
|
Utils::modify_timefuncname(pModule);
|
||||||
return pModule;
|
return pModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2403,4 +2405,12 @@ void Utils::initExternalFunction(Module *pModule, IRBuilder *pBuilder) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Utils::modify_timefuncname(Module *pModule){
|
||||||
|
auto starttimeFunc = pModule->getExternalFunction("starttime");
|
||||||
|
auto stoptimeFunc = pModule->getExternalFunction("stoptime");
|
||||||
|
starttimeFunc->setName("_sysy_starttime");
|
||||||
|
stoptimeFunc->setName("_sysy_stoptime");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sysy
|
} // namespace sysy
|
||||||
Reference in New Issue
Block a user