[midend-SCCP]bug修复,增加不可达指令(理论来说后端不会出现这条指令,只是为了IR完整性添加),添加相关方法,phi指令方法修复;目前能够跑完所有优化,但是User的析构函数重定义导致全局析构不能正确完成,需要修复

This commit is contained in:
rain2133
2025-07-31 22:03:35 +08:00
parent 9a53e1b917
commit c5af4f1c49
6 changed files with 73 additions and 88 deletions

View File

@@ -710,7 +710,7 @@ class Instruction : public User {
kCondBr = 0x1UL << 30, kCondBr = 0x1UL << 30,
kBr = 0x1UL << 31, kBr = 0x1UL << 31,
kReturn = 0x1UL << 32, kReturn = 0x1UL << 32,
kUnreachable = 0x1UL << 32, ///< Unreachable instruction, used for optimization purposes kUnreachable = 0x1UL << 33,
// mem op // mem op
kAlloca = 0x1UL << 34, kAlloca = 0x1UL << 34,
kLoad = 0x1UL << 35, kLoad = 0x1UL << 35,
@@ -845,7 +845,7 @@ public:
return kind & MemoryOpMask; return kind & MemoryOpMask;
} }
bool isTerminator() const { bool isTerminator() const {
static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn; static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn | kUnreachable;
return kind & TerminatorOpMask; return kind & TerminatorOpMask;
} }
bool isCmp() const { bool isCmp() const {
@@ -874,6 +874,7 @@ public:
bool isMemset() const { return kind == kMemset; } bool isMemset() const { return kind == kMemset; }
bool isCall() const { return kind == kCall; } bool isCall() const { return kind == kCall; }
bool isReturn() const { return kind == kReturn; } bool isReturn() const { return kind == kReturn; }
bool isUnreachable() const { return kind == kUnreachable; }
bool isDefine() const { bool isDefine() const {
static constexpr uint64_t DefineOpMask = kAlloca | kStore | kPhi; static constexpr uint64_t DefineOpMask = kAlloca | kStore | kPhi;
return (kind & DefineOpMask) != 0U; return (kind & DefineOpMask) != 0U;

View File

@@ -2,6 +2,7 @@
#include "IR.h" #include "IR.h"
extern int DEBUG;
namespace sysy { namespace sysy {
// 优化工具类,包含一些通用的优化方法 // 优化工具类,包含一些通用的优化方法
@@ -22,70 +23,39 @@ public:
} }
}; };
static void __internal_handle_instruction_deletion_uses(Instruction *inst_to_delete) { static void usedelete(Instruction *inst) {
assert(inst_to_delete && "Instruction to delete cannot be null."); assert(inst && "Instruction to delete cannot be null.");
// 确保指令有一个父基本块,才能进行后续的物理删除 BasicBlock *parentBlock = inst->getParent();
BasicBlock *parentBlock = inst_to_delete->getParent();
assert(parentBlock && "Instruction must have a parent BasicBlock to be deleted."); assert(parentBlock && "Instruction must have a parent BasicBlock to be deleted.");
// 如果指令定义了一个值并且仍然有使用者(即它的 getUses() 不为空), // 直接在此处执行 replaceAllUsesWith
// 那么将其所有用途替换为对应类型的 UndefinedValue。 if (!inst->getUses().empty()) {
// 这是一种安全的做法,避免悬空指针,同时表示这些值是未定义的。 if(DEBUG) {
// 如果指令本身不产生值(如 StoreInst, BranchInst 等),或者没有用户, std::cout << "Replacing all uses of instruction " << inst->getName() << " with UndefinedValue." << std::endl;
// getUses().empty() 会为 truereplaceAllUsesWith 将是一个空操作,这也是正确的。
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()));
} }
// 至此inst_to_delete 在语义上已不再被其他活跃指令使用。 // 替换所有使用该指令的地方为未定义值
inst->replaceAllUsesWith(UndefinedValue::get(inst->getType()));
} }
// 物理删除指令
// 版本1: 传入 Instruction*
static void usedelete(Instruction *inst) {
__internal_handle_instruction_deletion_uses(inst);
// 物理删除指令。BasicBlock::removeInst(Instruction*) 会在内部查找指令。
// 这行调用会触发 inst 指针所指向的 Instruction 对象的析构。
inst->getParent()->removeInst(inst); inst->getParent()->removeInst(inst);
} }
// 版本2: 传入 BasicBlock::iterator
static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) { static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) {
// 获取 unique_ptr 中的原始 Instruction 指针。
// 必须在物理删除操作之前获取因为物理删除后迭代器和unique_ptr可能失效。
Instruction *inst_to_delete = inst_it->get(); 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); // 直接在此处执行 replaceAllUsesWith
if (!inst_to_delete->getUses().empty()) {
// 物理删除指令。BasicBlock::removeInst(iterator pos) 更适合 std::list if(DEBUG) {
// 并且会返回一个新的迭代器,指向被删除元素之后的位置。 std::cout << "Replacing all uses of instruction " << inst_to_delete->getName() << " with UndefinedValue." << std::endl;
// 这行调用会触发 inst_to_delete 指向的 Instruction 对象的析构。 }
BasicBlock *parentBlock = inst_to_delete->getParent(); // 再次获取父块,以防万一 inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType()));
// 这里调用的是 BasicBlock 中修改后的 removeInst(iterator pos) 版本 }
// 物理删除指令
return parentBlock->removeInst(inst_it); 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) { static bool isGlobal(Value *val) {
auto gval = dynamic_cast<GlobalValue *>(val); auto gval = dynamic_cast<GlobalValue *>(val);

View File

@@ -569,7 +569,7 @@ void User::replaceOperand(unsigned index, Value *value) {
* phi相关函数 * phi相关函数
*/ */
Value* PhiInst::getvalfromBlk(BasicBlock* blk){ Value* PhiInst::getvalfromBlk(BasicBlock* blk){
refreshB2VMap(); refreshB2VMap();
if( blk2val.find(blk) != blk2val.end()) { if( blk2val.find(blk) != blk2val.end()) {
return blk2val.at(blk); return blk2val.at(blk);
@@ -619,11 +619,13 @@ void PhiInst::delBlk(BasicBlock* blk){
void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){ void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){
refreshB2VMap(); 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); setOperand(2 * k + 1, newBlk);
// 替换blk2val映射 // 替换blk2val映射
blk2val.erase(getBlock(k)); blk2val.erase(oldBlk);
blk2val.emplace(newBlk, val); blk2val.emplace(newBlk, val);
} }

View File

@@ -433,6 +433,7 @@ void SCCPContext::ProcessInstruction(Instruction *inst) {
case Instruction::kBr: // 对应 kBr case Instruction::kBr: // 对应 kBr
case Instruction::kCondBr: // 对应 kCondBr case Instruction::kCondBr: // 对应 kCondBr
case Instruction::kReturn: // 对应 kReturn case Instruction::kReturn: // 对应 kReturn
case Instruction::kUnreachable: // 对应 kUnreachable
// 终结符指令不产生值 // 终结符指令不产生值
newState = SSAPValue(); // 保持 Top newState = SSAPValue(); // 保持 Top
break; break;
@@ -451,8 +452,10 @@ void SCCPContext::ProcessInstruction(Instruction *inst) {
// 特殊处理终结符指令,影响 CFG 边的可达性 // 特殊处理终结符指令,影响 CFG 边的可达性
if (inst->isTerminator()) { if (inst->isTerminator()) {
if (auto branchInst = dynamic_cast<CondBrInst *>(inst)) { if (inst->isBranch()) {
if (branchInst->isCondBr()) { // 使用 kCondBr
if (inst->isCondBr()) { // 使用 kCondBr
CondBrInst *branchInst = static_cast<CondBrInst *>(inst);
SSAPValue condVal = GetValueState(branchInst->getOperand(0)); SSAPValue condVal = GetValueState(branchInst->getOperand(0));
if (condVal.state == LatticeVal::Constant) { if (condVal.state == LatticeVal::Constant) {
bool condition_is_true = false; bool condition_is_true = false;
@@ -472,7 +475,8 @@ void SCCPContext::ProcessInstruction(Instruction *inst) {
AddEdgeToWorkList(branchInst->getParent(), branchInst->getElseBlock()); AddEdgeToWorkList(branchInst->getParent(), branchInst->getElseBlock());
} }
} else { // 无条件分支 (kBr) } else { // 无条件分支 (kBr)
AddEdgeToWorkList(branchInst->getParent(), branchInst->getThenBlock()); UncondBrInst *branchInst = static_cast<UncondBrInst *>(inst);
AddEdgeToWorkList(branchInst->getParent(), branchInst->getBlock());
} }
} }
} }
@@ -560,8 +564,7 @@ bool SCCPContext::PropagateConstants(Function *func) {
} }
inst->replaceAllUsesWith(constVal); inst->replaceAllUsesWith(constVal);
instsToDelete.push_back(inst); instsToDelete.push_back(inst);
// it = bb->removeInst(it); // 从块中移除指令 ++it;
it = bb->getInstructions().erase(it);
changed = true; changed = true;
} else { } else {
// 如果操作数是常量,直接替换为常量值(常量折叠) // 如果操作数是常量,直接替换为常量值(常量折叠)
@@ -595,14 +598,7 @@ bool SCCPContext::PropagateConstants(Function *func) {
// 如果它已经没有父块,可能说明它已被其他方式处理或已处于无效状态。 // 如果它已经没有父块,可能说明它已被其他方式处理或已处于无效状态。
if (inst->getParent() != nullptr) { if (inst->getParent() != nullptr) {
// 调用负责完整删除的函数该函数应负责清除uses并将其从父块中移除。 // 调用负责完整删除的函数该函数应负责清除uses并将其从父块中移除。
SysYIROptUtils::usedelete_withinstdelte(inst); SysYIROptUtils::usedelete(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;
}
}
} }
else { else {
// 指令已不属于任何父块,无需再次删除。 // 指令已不属于任何父块,无需再次删除。
@@ -642,8 +638,10 @@ bool SCCPContext::SimplifyControlFlow(Function *func) {
continue; // 只处理可达块 continue; // 只处理可达块
Instruction *terminator = bb->terminator()->get(); Instruction *terminator = bb->terminator()->get();
if (auto branchInst = dynamic_cast<CondBrInst *>(terminator)) { if (terminator->isBranch()) {
if (branchInst->isCondBr()) { // 检查是否是条件分支 (kCondBr)
if (terminator->isCondBr()) { // 检查是否是条件分支 (kCondBr)
CondBrInst *branchInst = static_cast<CondBrInst *>(terminator);
SSAPValue condVal = GetValueState(branchInst->getOperand(0)); SSAPValue condVal = GetValueState(branchInst->getOperand(0));
if (condVal.state == LatticeVal::Constant) { if (condVal.state == LatticeVal::Constant) {
bool condition_is_true = false; bool condition_is_true = false;
@@ -680,8 +678,9 @@ std::unordered_set<BasicBlock *> SCCPContext::FindReachableBlocks(Function *func
if (!terminator) if (!terminator)
continue; continue;
if (auto branchInst = dynamic_cast<CondBrInst *>(terminator)) { if (terminator->isBranch()) {
if (branchInst->isCondBr()) { // 检查是否是条件分支 (kCondBr) if (terminator->isCondBr()) { // 检查是否是条件分支 (kCondBr)
CondBrInst *branchInst = static_cast<CondBrInst *>(terminator);
SSAPValue condVal = GetValueState(branchInst->getOperand(0)); SSAPValue condVal = GetValueState(branchInst->getOperand(0));
if (condVal.state == LatticeVal::Constant) { if (condVal.state == LatticeVal::Constant) {
bool condition_is_true = false; bool condition_is_true = false;
@@ -713,14 +712,16 @@ std::unordered_set<BasicBlock *> SCCPContext::FindReachableBlocks(Function *func
} }
} }
} else { // 无条件分支 (kBr) } else { // 无条件分支 (kBr)
BasicBlock *targetBlock = branchInst->getThenBlock(); UncondBrInst *branchInst = static_cast<UncondBrInst *>(terminator);
BasicBlock *targetBlock = branchInst->getBlock();
if (reachable.find(targetBlock) == reachable.end()) { if (reachable.find(targetBlock) == reachable.end()) {
reachable.insert(targetBlock); reachable.insert(targetBlock);
q.push(targetBlock); q.push(targetBlock);
} }
} }
} else if (auto retInst = dynamic_cast<ReturnInst *>(terminator)) { } else if (terminator->isReturn() || terminator->isUnreachable()) {
// ReturnInst 没有后继,不需要处理 // ReturnInst 没有后继,不需要处理
// UnreachableInst 也没有后继,不需要处理
} }
} }
return reachable; return reachable;
@@ -771,16 +772,12 @@ void SCCPContext::SimplifyBranch(CondBrInst *brInst, bool condVal) {
if (condVal) { // 条件为真,跳转到真分支 if (condVal) { // 条件为真,跳转到真分支
builder->createUncondBrInst(trueBlock); // 插入无条件分支 kBr builder->createUncondBrInst(trueBlock); // 插入无条件分支 kBr
SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令 SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令
// TODO now 移出指令
parentBB->removeSuccessor(falseBlock); parentBB->removeSuccessor(falseBlock);
falseBlock->removePredecessor(parentBB); falseBlock->removePredecessor(parentBB);
RemovePhiIncoming(falseBlock, parentBB); RemovePhiIncoming(falseBlock, parentBB);
} else { // 条件为假,跳转到假分支 } else { // 条件为假,跳转到假分支
builder->createUncondBrInst(falseBlock); // 插入无条件分支 kBr builder->createUncondBrInst(falseBlock); // 插入无条件分支 kBr
SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令 SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令
// TODO now 移出指令
parentBB->removeSuccessor(trueBlock); parentBB->removeSuccessor(trueBlock);
trueBlock->removePredecessor(parentBB); trueBlock->removePredecessor(parentBB);
RemovePhiIncoming(trueBlock, parentBB); RemovePhiIncoming(trueBlock, parentBB);
@@ -793,8 +790,9 @@ void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc)
if (!terminator) if (!terminator)
return; return;
if (auto branchInst = dynamic_cast<CondBrInst *>(terminator)) { if (terminator->isBranch()) {
if (branchInst->isCondBr()) { // 如果是条件分支 if (terminator->isCondBr()) { // 如果是条件分支
CondBrInst *branchInst = static_cast<CondBrInst *>(terminator);
if (branchInst->getThenBlock() == removedSucc) { if (branchInst->getThenBlock() == removedSucc) {
if (DEBUG) { if (DEBUG) {
std::cout << "Updating cond br in " << predBB->getName() << ": True block (" << removedSucc->getName() 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->setPosition(predBB, predBB->findInstIterator(branchInst));
builder->createUncondBrInst(branchInst->getElseBlock()); builder->createUncondBrInst(branchInst->getElseBlock());
SysYIROptUtils::usedelete_withinstdelte(branchInst); SysYIROptUtils::usedelete(branchInst);
predBB->removeSuccessor(removedSucc); predBB->removeSuccessor(removedSucc);
} else if (branchInst->getElseBlock() == removedSucc) { } else if (branchInst->getElseBlock() == removedSucc) {
if (DEBUG) { if (DEBUG) {
@@ -811,16 +809,17 @@ void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc)
} }
builder->setPosition(predBB, predBB->findInstIterator(branchInst)); builder->setPosition(predBB, predBB->findInstIterator(branchInst));
builder->createUncondBrInst(branchInst->getThenBlock()); builder->createUncondBrInst(branchInst->getThenBlock());
SysYIROptUtils::usedelete_withinstdelte(branchInst); SysYIROptUtils::usedelete(branchInst);
predBB->removeSuccessor(removedSucc); predBB->removeSuccessor(removedSucc);
} }
} else { // 无条件分支 (kBr) } else { // 无条件分支 (kBr)
if (branchInst->getThenBlock() == removedSucc) { UncondBrInst *branchInst = static_cast<UncondBrInst *>(terminator);
if (branchInst->getBlock() == removedSucc) {
if (DEBUG) { if (DEBUG) {
std::cout << "Updating unconditional br in " << predBB->getName() << ": Target block (" std::cout << "Updating unconditional br in " << predBB->getName() << ": Target block ("
<< removedSucc->getName() << ") removed. Replacing with Unreachable." << std::endl; << removedSucc->getName() << ") removed. Replacing with Unreachable." << std::endl;
} }
SysYIROptUtils::usedelete_withinstdelte(branchInst); SysYIROptUtils::usedelete(branchInst);
predBB->removeSuccessor(removedSucc); predBB->removeSuccessor(removedSucc);
builder->setPosition(predBB, predBB->end()); builder->setPosition(predBB, predBB->end());
builder->createUnreachableInst(); builder->createUnreachableInst();

View File

@@ -83,11 +83,19 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
this->clearPasses(); this->clearPasses();
this->addPass(&Mem2Reg::ID); this->addPass(&Mem2Reg::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After Mem2Reg Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&SCCP::ID); this->addPass(&SCCP::ID);
this->run(); this->run();
if(DEBUG) { if(DEBUG) {
std::cout << "=== IR After Mem2Reg And SCCP Optimizations ===\n"; std::cout << "=== IR After SCCP Optimizations ===\n";
printPasses(); printPasses();
} }

View File

@@ -401,6 +401,11 @@ void SysYPrinter::printInst(Instruction *pInst) {
std::cout << std::endl; std::cout << std::endl;
} break; } break;
case Kind::kUnreachable: {
std::cout << "Unreachable" << std::endl;
} break;
case Kind::kAlloca: { case Kind::kAlloca: {
auto allocaInst = dynamic_cast<AllocaInst *>(pInst); auto allocaInst = dynamic_cast<AllocaInst *>(pInst);
std::cout << "%" << allocaInst->getName() << " = alloca "; std::cout << "%" << allocaInst->getName() << " = alloca ";