[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,
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;

View File

@@ -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() 会为 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()));
// 直接在此处执行 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<GlobalValue *>(val);