Merge commit '07fd22def182a12999de6ae0c9447056fb9d7a40' into backend
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
namespace sysy {
|
||||
|
||||
char PeepholeOptimizer::ID = 0;
|
||||
bool PeepholeOptimizer::fusedMulAddEnabled = true; // 默认启用浮点乘加融合优化
|
||||
|
||||
bool PeepholeOptimizer::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||
// This pass works on MachineFunction level, not IR level
|
||||
@@ -634,6 +635,99 @@ void PeepholeOptimizer::runOnMachineFunction(MachineFunction *mfunc) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 8. 浮点乘加融合优化
|
||||
// 8.1 fmul.s t1, t2, t3; fadd.s t4, t1, t5 -> fmadd.s t4, t2, t3, t5
|
||||
else if (isFusedMulAddEnabled() &&
|
||||
mi1->getOpcode() == RVOpcodes::FMUL_S &&
|
||||
mi2->getOpcode() == RVOpcodes::FADD_S) {
|
||||
if (mi1->getOperands().size() == 3 && mi2->getOperands().size() == 3) {
|
||||
auto *fmul_dst = static_cast<RegOperand *>(mi1->getOperands()[0].get());
|
||||
auto *fmul_src1 = static_cast<RegOperand *>(mi1->getOperands()[1].get());
|
||||
auto *fmul_src2 = static_cast<RegOperand *>(mi1->getOperands()[2].get());
|
||||
|
||||
auto *fadd_dst = static_cast<RegOperand *>(mi2->getOperands()[0].get());
|
||||
auto *fadd_src1 = static_cast<RegOperand *>(mi2->getOperands()[1].get());
|
||||
auto *fadd_src2 = static_cast<RegOperand *>(mi2->getOperands()[2].get());
|
||||
|
||||
// 检查fmul的目标是否是fadd的第一个源操作数
|
||||
if (areRegsEqual(fmul_dst, fadd_src1)) {
|
||||
// 检查中间寄存器是否在后续还会被使用
|
||||
bool canOptimize = true;
|
||||
for (size_t j = i + 2; j < instrs.size(); ++j) {
|
||||
auto *later_instr = instrs[j].get();
|
||||
|
||||
// 如果中间寄存器被重新定义,则可以优化
|
||||
if (isRegRedefinedAt(later_instr, fmul_dst, areRegsEqual)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 如果中间寄存器被使用,则不能优化
|
||||
if (isRegUsedLater(instrs, fmul_dst, j)) {
|
||||
canOptimize = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (canOptimize) {
|
||||
// 创建新的FMADD_S指令: fmadd.s t4, t2, t3, t5
|
||||
auto newInstr = std::make_unique<MachineInstr>(RVOpcodes::FMADD_S);
|
||||
newInstr->addOperand(std::make_unique<RegOperand>(*fadd_dst));
|
||||
newInstr->addOperand(std::make_unique<RegOperand>(*fmul_src1));
|
||||
newInstr->addOperand(std::make_unique<RegOperand>(*fmul_src2));
|
||||
newInstr->addOperand(std::make_unique<RegOperand>(*fadd_src2));
|
||||
instrs[i + 1] = std::move(newInstr);
|
||||
instrs.erase(instrs.begin() + i);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 8.2 fmul.s t1, t2, t3; fadd.s t4, t5, t1 -> fmadd.s t4, t2, t3, t5
|
||||
else if (isFusedMulAddEnabled() &&
|
||||
mi1->getOpcode() == RVOpcodes::FMUL_S &&
|
||||
mi2->getOpcode() == RVOpcodes::FADD_S) {
|
||||
if (mi1->getOperands().size() == 3 && mi2->getOperands().size() == 3) {
|
||||
auto *fmul_dst = static_cast<RegOperand *>(mi1->getOperands()[0].get());
|
||||
auto *fmul_src1 = static_cast<RegOperand *>(mi1->getOperands()[1].get());
|
||||
auto *fmul_src2 = static_cast<RegOperand *>(mi1->getOperands()[2].get());
|
||||
|
||||
auto *fadd_dst = static_cast<RegOperand *>(mi2->getOperands()[0].get());
|
||||
auto *fadd_src1 = static_cast<RegOperand *>(mi2->getOperands()[1].get());
|
||||
auto *fadd_src2 = static_cast<RegOperand *>(mi2->getOperands()[2].get());
|
||||
|
||||
// 检查fmul的目标是否是fadd的第二个源操作数
|
||||
if (areRegsEqual(fmul_dst, fadd_src2)) {
|
||||
// 检查中间寄存器是否在后续还会被使用
|
||||
bool canOptimize = true;
|
||||
for (size_t j = i + 2; j < instrs.size(); ++j) {
|
||||
auto *later_instr = instrs[j].get();
|
||||
|
||||
// 如果中间寄存器被重新定义,则可以优化
|
||||
if (isRegRedefinedAt(later_instr, fmul_dst, areRegsEqual)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 如果中间寄存器被使用,则不能优化
|
||||
if (isRegUsedLater(instrs, fmul_dst, j)) {
|
||||
canOptimize = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (canOptimize) {
|
||||
// 创建新的FMADD_S指令: fmadd.s t4, t2, t3, t5
|
||||
auto newInstr = std::make_unique<MachineInstr>(RVOpcodes::FMADD_S);
|
||||
newInstr->addOperand(std::make_unique<RegOperand>(*fadd_dst));
|
||||
newInstr->addOperand(std::make_unique<RegOperand>(*fmul_src1));
|
||||
newInstr->addOperand(std::make_unique<RegOperand>(*fmul_src2));
|
||||
newInstr->addOperand(std::make_unique<RegOperand>(*fadd_src1));
|
||||
instrs[i + 1] = std::move(newInstr);
|
||||
instrs.erase(instrs.begin() + i);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据是否发生变化调整遍历索引
|
||||
if (!changed) {
|
||||
|
||||
@@ -79,6 +79,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
|
||||
case RVOpcodes::FSUB_S: *OS << "fsub.s "; break;
|
||||
case RVOpcodes::FMUL_S: *OS << "fmul.s "; break;
|
||||
case RVOpcodes::FDIV_S: *OS << "fdiv.s "; break;
|
||||
case RVOpcodes::FMADD_S: *OS << "fmadd.s "; break;
|
||||
case RVOpcodes::FNEG_S: *OS << "fneg.s "; break;
|
||||
case RVOpcodes::FEQ_S: *OS << "feq.s "; break;
|
||||
case RVOpcodes::FLT_S: *OS << "flt.s "; break;
|
||||
|
||||
Reference in New Issue
Block a user