From c5af4f1c494fe6877b690e9d8f173e7b26b12935 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 22:03:35 +0800 Subject: [PATCH] =?UTF-8?q?[midend-SCCP]bug=E4=BF=AE=E5=A4=8D=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=8D=E5=8F=AF=E8=BE=BE=E6=8C=87=E4=BB=A4?= =?UTF-8?q?=EF=BC=88=E7=90=86=E8=AE=BA=E6=9D=A5=E8=AF=B4=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E4=B8=8D=E4=BC=9A=E5=87=BA=E7=8E=B0=E8=BF=99=E6=9D=A1=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=EF=BC=8C=E5=8F=AA=E6=98=AF=E4=B8=BA=E4=BA=86IR?= =?UTF-8?q?=E5=AE=8C=E6=95=B4=E6=80=A7=E6=B7=BB=E5=8A=A0=EF=BC=89=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=9B=B8=E5=85=B3=E6=96=B9=E6=B3=95=EF=BC=8C?= =?UTF-8?q?phi=E6=8C=87=E4=BB=A4=E6=96=B9=E6=B3=95=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=EF=BC=9B=E7=9B=AE=E5=89=8D=E8=83=BD=E5=A4=9F=E8=B7=91=E5=AE=8C?= =?UTF-8?q?=E6=89=80=E6=9C=89=E4=BC=98=E5=8C=96=EF=BC=8C=E4=BD=86=E6=98=AF?= =?UTF-8?q?User=E7=9A=84=E6=9E=90=E6=9E=84=E5=87=BD=E6=95=B0=E9=87=8D?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E5=AF=BC=E8=87=B4=E5=85=A8=E5=B1=80=E6=9E=90?= =?UTF-8?q?=E6=9E=84=E4=B8=8D=E8=83=BD=E6=AD=A3=E7=A1=AE=E5=AE=8C=E6=88=90?= =?UTF-8?q?=EF=BC=8C=E9=9C=80=E8=A6=81=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/IR.h | 5 +- .../midend/Pass/Optimize/SysYIROptUtils.h | 74 ++++++------------- src/midend/IR.cpp | 8 +- src/midend/Pass/Optimize/SCCP.cpp | 57 +++++++------- src/midend/Pass/Pass.cpp | 10 ++- src/midend/SysYIRPrinter.cpp | 7 +- 6 files changed, 73 insertions(+), 88 deletions(-) diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index ab430f3..ec5ef5d 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -710,7 +710,7 @@ class Instruction : public User { kCondBr = 0x1UL << 30, kBr = 0x1UL << 31, kReturn = 0x1UL << 32, - kUnreachable = 0x1UL << 32, ///< Unreachable instruction, used for optimization purposes + kUnreachable = 0x1UL << 33, // mem op kAlloca = 0x1UL << 34, kLoad = 0x1UL << 35, @@ -845,7 +845,7 @@ public: return kind & MemoryOpMask; } bool isTerminator() const { - static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn; + static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn | kUnreachable; return kind & TerminatorOpMask; } bool isCmp() const { @@ -874,6 +874,7 @@ public: bool isMemset() const { return kind == kMemset; } bool isCall() const { return kind == kCall; } bool isReturn() const { return kind == kReturn; } + bool isUnreachable() const { return kind == kUnreachable; } bool isDefine() const { static constexpr uint64_t DefineOpMask = kAlloca | kStore | kPhi; return (kind & DefineOpMask) != 0U; diff --git a/src/include/midend/Pass/Optimize/SysYIROptUtils.h b/src/include/midend/Pass/Optimize/SysYIROptUtils.h index a5a757d..b4c6bbb 100644 --- a/src/include/midend/Pass/Optimize/SysYIROptUtils.h +++ b/src/include/midend/Pass/Optimize/SysYIROptUtils.h @@ -2,6 +2,7 @@ #include "IR.h" +extern int DEBUG; namespace sysy { // 优化工具类,包含一些通用的优化方法 @@ -22,70 +23,39 @@ public: } }; - static void __internal_handle_instruction_deletion_uses(Instruction *inst_to_delete) { - assert(inst_to_delete && "Instruction to delete cannot be null."); - // 确保指令有一个父基本块,才能进行后续的物理删除 - BasicBlock *parentBlock = inst_to_delete->getParent(); + static void usedelete(Instruction *inst) { + assert(inst && "Instruction to delete cannot be null."); + BasicBlock *parentBlock = inst->getParent(); assert(parentBlock && "Instruction must have a parent BasicBlock to be deleted."); - // 如果指令定义了一个值并且仍然有使用者(即它的 getUses() 不为空), - // 那么将其所有用途替换为对应类型的 UndefinedValue。 - // 这是一种安全的做法,避免悬空指针,同时表示这些值是未定义的。 - // 如果指令本身不产生值(如 StoreInst, BranchInst 等),或者没有用户, - // getUses().empty() 会为 true,replaceAllUsesWith 将是一个空操作,这也是正确的。 - if (!inst_to_delete->getUses().empty()) { - // UndefinedValue::get(Type*) 需要一个 Type* 参数,确保类型匹配。 - // 例如,如果 inst_to_delete 是 alloca i32,那么它的类型是 PointerType (i32*)。 - // UndefinedValue::get 的参数应是 i32* 类型。 - std::cout << "Replacing uses of instruction " << inst_to_delete->getName() - << " with UndefinedValue." << std::endl; - inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType())); + // 直接在此处执行 replaceAllUsesWith + if (!inst->getUses().empty()) { + if(DEBUG) { + std::cout << "Replacing all uses of instruction " << inst->getName() << " with UndefinedValue." << std::endl; + } + // 替换所有使用该指令的地方为未定义值 + inst->replaceAllUsesWith(UndefinedValue::get(inst->getType())); } - // 至此,inst_to_delete 在语义上已不再被其他活跃指令使用。 - } - - // 版本1: 传入 Instruction* - static void usedelete(Instruction *inst) { - __internal_handle_instruction_deletion_uses(inst); - - // 物理删除指令。BasicBlock::removeInst(Instruction*) 会在内部查找指令。 - // 这行调用会触发 inst 指针所指向的 Instruction 对象的析构。 + // 物理删除指令 inst->getParent()->removeInst(inst); } - // 版本2: 传入 BasicBlock::iterator static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) { - // 获取 unique_ptr 中的原始 Instruction 指针。 - // 必须在物理删除操作之前获取,因为物理删除后迭代器和unique_ptr可能失效。 Instruction *inst_to_delete = inst_it->get(); + BasicBlock *parentBlock = inst_to_delete->getParent(); + assert(parentBlock && "Instruction must have a parent BasicBlock for iterator deletion."); - __internal_handle_instruction_deletion_uses(inst_to_delete); - - // 物理删除指令。BasicBlock::removeInst(iterator pos) 更适合 std::list, - // 并且会返回一个新的迭代器,指向被删除元素之后的位置。 - // 这行调用会触发 inst_to_delete 指向的 Instruction 对象的析构。 - BasicBlock *parentBlock = inst_to_delete->getParent(); // 再次获取父块,以防万一 - // 这里调用的是 BasicBlock 中修改后的 removeInst(iterator pos) 版本 + // 直接在此处执行 replaceAllUsesWith + if (!inst_to_delete->getUses().empty()) { + if(DEBUG) { + std::cout << "Replacing all uses of instruction " << inst_to_delete->getName() << " with UndefinedValue." << std::endl; + } + inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType())); + } + // 物理删除指令 return parentBlock->removeInst(inst_it); } - // 仅仅删除use关系 - // static void usedelete(Instruction *instr) { - // for (auto &use : instr->getOperands()) { - // Value* val = use->getValue(); - // val->removeUse(use); - // } - // } - - // // 删除use关系并删除指令 - // static void usedelete_withinstdelte(Instruction *instr) { - // for (auto &use : instr->getOperands()) { - // Value* val = use->getValue(); - // val->removeUse(use); - // } - // instr->getParent()->removeInst(instr); - // } - // 判断是否是全局变量 static bool isGlobal(Value *val) { auto gval = dynamic_cast(val); diff --git a/src/midend/IR.cpp b/src/midend/IR.cpp index bee9968..0fd6198 100644 --- a/src/midend/IR.cpp +++ b/src/midend/IR.cpp @@ -569,7 +569,7 @@ void User::replaceOperand(unsigned index, Value *value) { * phi相关函数 */ - Value* PhiInst::getvalfromBlk(BasicBlock* blk){ +Value* PhiInst::getvalfromBlk(BasicBlock* blk){ refreshB2VMap(); if( blk2val.find(blk) != blk2val.end()) { return blk2val.at(blk); @@ -619,11 +619,13 @@ void PhiInst::delBlk(BasicBlock* blk){ void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){ refreshB2VMap(); - Value* val = blk2val.at(getBlock(k)); + BasicBlock* oldBlk = getBlock(k); + Value* val = blk2val.at(oldBlk); + // Value* val = blk2val.at(getBlock(k)); // 替换基本块 setOperand(2 * k + 1, newBlk); // 替换blk2val映射 - blk2val.erase(getBlock(k)); + blk2val.erase(oldBlk); blk2val.emplace(newBlk, val); } diff --git a/src/midend/Pass/Optimize/SCCP.cpp b/src/midend/Pass/Optimize/SCCP.cpp index 6c492dc..3cc2d48 100644 --- a/src/midend/Pass/Optimize/SCCP.cpp +++ b/src/midend/Pass/Optimize/SCCP.cpp @@ -433,6 +433,7 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { case Instruction::kBr: // 对应 kBr case Instruction::kCondBr: // 对应 kCondBr case Instruction::kReturn: // 对应 kReturn + case Instruction::kUnreachable: // 对应 kUnreachable // 终结符指令不产生值 newState = SSAPValue(); // 保持 Top break; @@ -451,8 +452,10 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { // 特殊处理终结符指令,影响 CFG 边的可达性 if (inst->isTerminator()) { - if (auto branchInst = dynamic_cast(inst)) { - if (branchInst->isCondBr()) { // 使用 kCondBr + if (inst->isBranch()) { + + if (inst->isCondBr()) { // 使用 kCondBr + CondBrInst *branchInst = static_cast(inst); SSAPValue condVal = GetValueState(branchInst->getOperand(0)); if (condVal.state == LatticeVal::Constant) { bool condition_is_true = false; @@ -472,7 +475,8 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { AddEdgeToWorkList(branchInst->getParent(), branchInst->getElseBlock()); } } else { // 无条件分支 (kBr) - AddEdgeToWorkList(branchInst->getParent(), branchInst->getThenBlock()); + UncondBrInst *branchInst = static_cast(inst); + AddEdgeToWorkList(branchInst->getParent(), branchInst->getBlock()); } } } @@ -560,8 +564,7 @@ bool SCCPContext::PropagateConstants(Function *func) { } inst->replaceAllUsesWith(constVal); instsToDelete.push_back(inst); - // it = bb->removeInst(it); // 从块中移除指令 - it = bb->getInstructions().erase(it); + ++it; changed = true; } else { // 如果操作数是常量,直接替换为常量值(常量折叠) @@ -595,14 +598,7 @@ bool SCCPContext::PropagateConstants(Function *func) { // 如果它已经没有父块,可能说明它已被其他方式处理或已处于无效状态。 if (inst->getParent() != nullptr) { // 调用负责完整删除的函数,该函数应负责清除uses并将其从父块中移除。 - SysYIROptUtils::usedelete_withinstdelte(inst); - if (inst->getParent() != nullptr) { - // 如果执行到这里,说明 usedelete_withinstdelte 没有成功将其从父块中移除。 - if (DEBUG) { - std::cerr << "Warning: Instruction " << inst->getName() - << " was not fully deleted by usedelete_withinstdelte and is still in parent." << std::endl; - } - } + SysYIROptUtils::usedelete(inst); } else { // 指令已不属于任何父块,无需再次删除。 @@ -642,8 +638,10 @@ bool SCCPContext::SimplifyControlFlow(Function *func) { continue; // 只处理可达块 Instruction *terminator = bb->terminator()->get(); - if (auto branchInst = dynamic_cast(terminator)) { - if (branchInst->isCondBr()) { // 检查是否是条件分支 (kCondBr) + if (terminator->isBranch()) { + + if (terminator->isCondBr()) { // 检查是否是条件分支 (kCondBr) + CondBrInst *branchInst = static_cast(terminator); SSAPValue condVal = GetValueState(branchInst->getOperand(0)); if (condVal.state == LatticeVal::Constant) { bool condition_is_true = false; @@ -680,8 +678,9 @@ std::unordered_set SCCPContext::FindReachableBlocks(Function *func if (!terminator) continue; - if (auto branchInst = dynamic_cast(terminator)) { - if (branchInst->isCondBr()) { // 检查是否是条件分支 (kCondBr) + if (terminator->isBranch()) { + if (terminator->isCondBr()) { // 检查是否是条件分支 (kCondBr) + CondBrInst *branchInst = static_cast(terminator); SSAPValue condVal = GetValueState(branchInst->getOperand(0)); if (condVal.state == LatticeVal::Constant) { bool condition_is_true = false; @@ -713,14 +712,16 @@ std::unordered_set SCCPContext::FindReachableBlocks(Function *func } } } else { // 无条件分支 (kBr) - BasicBlock *targetBlock = branchInst->getThenBlock(); + UncondBrInst *branchInst = static_cast(terminator); + BasicBlock *targetBlock = branchInst->getBlock(); if (reachable.find(targetBlock) == reachable.end()) { reachable.insert(targetBlock); q.push(targetBlock); } } - } else if (auto retInst = dynamic_cast(terminator)) { + } else if (terminator->isReturn() || terminator->isUnreachable()) { // ReturnInst 没有后继,不需要处理 + // UnreachableInst 也没有后继,不需要处理 } } return reachable; @@ -771,16 +772,12 @@ void SCCPContext::SimplifyBranch(CondBrInst *brInst, bool condVal) { if (condVal) { // 条件为真,跳转到真分支 builder->createUncondBrInst(trueBlock); // 插入无条件分支 kBr SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令 - // TODO now: 移出指令 - parentBB->removeSuccessor(falseBlock); falseBlock->removePredecessor(parentBB); RemovePhiIncoming(falseBlock, parentBB); } else { // 条件为假,跳转到假分支 builder->createUncondBrInst(falseBlock); // 插入无条件分支 kBr SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令 - // TODO now: 移出指令 - parentBB->removeSuccessor(trueBlock); trueBlock->removePredecessor(parentBB); RemovePhiIncoming(trueBlock, parentBB); @@ -793,8 +790,9 @@ void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc) if (!terminator) return; - if (auto branchInst = dynamic_cast(terminator)) { - if (branchInst->isCondBr()) { // 如果是条件分支 + if (terminator->isBranch()) { + if (terminator->isCondBr()) { // 如果是条件分支 + CondBrInst *branchInst = static_cast(terminator); if (branchInst->getThenBlock() == removedSucc) { if (DEBUG) { std::cout << "Updating cond br in " << predBB->getName() << ": True block (" << removedSucc->getName() @@ -802,7 +800,7 @@ void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc) } builder->setPosition(predBB, predBB->findInstIterator(branchInst)); builder->createUncondBrInst(branchInst->getElseBlock()); - SysYIROptUtils::usedelete_withinstdelte(branchInst); + SysYIROptUtils::usedelete(branchInst); predBB->removeSuccessor(removedSucc); } else if (branchInst->getElseBlock() == removedSucc) { if (DEBUG) { @@ -811,16 +809,17 @@ void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc) } builder->setPosition(predBB, predBB->findInstIterator(branchInst)); builder->createUncondBrInst(branchInst->getThenBlock()); - SysYIROptUtils::usedelete_withinstdelte(branchInst); + SysYIROptUtils::usedelete(branchInst); predBB->removeSuccessor(removedSucc); } } else { // 无条件分支 (kBr) - if (branchInst->getThenBlock() == removedSucc) { + UncondBrInst *branchInst = static_cast(terminator); + if (branchInst->getBlock() == removedSucc) { if (DEBUG) { std::cout << "Updating unconditional br in " << predBB->getName() << ": Target block (" << removedSucc->getName() << ") removed. Replacing with Unreachable." << std::endl; } - SysYIROptUtils::usedelete_withinstdelte(branchInst); + SysYIROptUtils::usedelete(branchInst); predBB->removeSuccessor(removedSucc); builder->setPosition(predBB, predBB->end()); builder->createUnreachableInst(); diff --git a/src/midend/Pass/Pass.cpp b/src/midend/Pass/Pass.cpp index 8fbaeec..f4ec5ab 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -83,11 +83,19 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR this->clearPasses(); this->addPass(&Mem2Reg::ID); + this->run(); + + if(DEBUG) { + std::cout << "=== IR After Mem2Reg Optimizations ===\n"; + printPasses(); + } + + this->clearPasses(); this->addPass(&SCCP::ID); this->run(); if(DEBUG) { - std::cout << "=== IR After Mem2Reg And SCCP Optimizations ===\n"; + std::cout << "=== IR After SCCP Optimizations ===\n"; printPasses(); } diff --git a/src/midend/SysYIRPrinter.cpp b/src/midend/SysYIRPrinter.cpp index 61b9a6f..a673613 100644 --- a/src/midend/SysYIRPrinter.cpp +++ b/src/midend/SysYIRPrinter.cpp @@ -400,7 +400,12 @@ void SysYPrinter::printInst(Instruction *pInst) { } std::cout << std::endl; } break; - + + case Kind::kUnreachable: { + std::cout << "Unreachable" << std::endl; + + } break; + case Kind::kAlloca: { auto allocaInst = dynamic_cast(pInst); std::cout << "%" << allocaInst->getName() << " = alloca ";