[midend-SCCP]删除User的析构函数,usedelete增加逻辑通知inst所使用的value移除对应的use关系(一般在这之前会替换使用inst的uses为其他值),TODO:仍然存在bug需要调试

This commit is contained in:
rain2133
2025-07-31 22:32:04 +08:00
parent c5af4f1c49
commit 0f1fcc835d
3 changed files with 125 additions and 31 deletions

View File

@@ -626,21 +626,21 @@ class User : public Value {
explicit User(Type *type, const std::string &name = "") : Value(type, name) {}
public:
~User() override {
// 当 User 对象被销毁时例如LoadInst 或 StoreInst 被删除时),
// 它必须通知它所使用的所有 Value将对应的 Use 关系从它们的 uses 列表中移除。
// 这样可以防止 Value 的 uses 列表中出现悬空的 Use 对象。
for (const auto &use_ptr : operands) {
// 确保 use_ptr 非空,并且其内部指向的 Value* 也非空
// (虽然通常情况下不会为空,但为了健壮性考虑)
if (use_ptr && use_ptr->getValue()) {
use_ptr->getValue()->removeUse(use_ptr);
}
}
// operands 向量本身是 std::vector<std::shared_ptr<Use>>
// 在此析构函数结束后operands 向量会被销毁,其内部的 shared_ptr 也会被释放,
// 如果 shared_ptr 引用计数降为0Use 对象本身也会被销毁。
}
// ~User() override {
// // 当 User 对象被销毁时例如LoadInst 或 StoreInst 被删除时),
// // 它必须通知它所使用的所有 Value将对应的 Use 关系从它们的 uses 列表中移除。
// // 这样可以防止 Value 的 uses 列表中出现悬空的 Use 对象。
// for (const auto &use_ptr : operands) {
// // 确保 use_ptr 非空,并且其内部指向的 Value* 也非空
// // (虽然通常情况下不会为空,但为了健壮性考虑)
// if (use_ptr && use_ptr->getValue()) {
// use_ptr->getValue()->removeUse(use_ptr);
// }
// }
// // operands 向量本身是 std::vector<std::shared_ptr<Use>>
// // 在此析构函数结束后operands 向量会被销毁,其内部的 shared_ptr 也会被释放,
// // 如果 shared_ptr 引用计数降为0Use 对象本身也会被销毁。
// }
unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量
auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器
auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器

View File

@@ -23,38 +23,76 @@ public:
}
};
static void RemoveUserOperandUses(User *user) {
if (!user) {
return;
}
// 遍历 User 的 operands 列表。
// 由于 operands 是 protected 成员,我们需要一个临时方法来访问它,
// 或者在 User 类中添加一个 friend 声明。
// 假设 User 内部有一个像 getOperands() 这样的公共方法返回 operands 的引用,
// 或者将 SysYIROptUtils 声明为 User 的 friend。
// 为了示例,我将假设可以直接访问 user->operands 或通过一个getter。
// 如果无法直接访问,请在 IR.h 的 User 类中添加:
// public: const std::vector<std::shared_ptr<Use>>& getOperands() const { return operands; }
// 迭代 copies of shared_ptr to avoid issues if removeUse modifies the list
// (though remove should handle it, iterating a copy is safer or reverse iteration).
// Since we'll clear the vector at the end, iterating forward is fine.
for (const auto& use_ptr : user->getOperands()) { // 假设 getOperands() 可用
if (use_ptr) {
Value *val = use_ptr->getValue(); // 获取 Use 指向的 Value (如 AllocaInst)
if (val) {
val->removeUse(use_ptr); // 通知 Value 从其 uses 列表中移除此 Use 关系
}
}
}
// 清空 User 的 operands 向量。这会递减 User 持有的 shared_ptr<Use> 的引用计数。
// 当引用计数降为 0 时Use 对象本身将被销毁。
// User::operands.clear(); // 这个步骤会在 Instruction 的析构函数中自动完成,因为它是 vector 成员
// 或者我们可以在 User::removeOperand 方法中确保 Use 对象从 operands 中移除。
// 实际上,只要 Value::removeUse(use_ptr) 被调用了,
// 当 Instruction 所在的 unique_ptr 销毁时,它的 operands vector 也会被销毁。
// 所以这里不需要显式 clear()
}
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.");
// 直接在此处执行 replaceAllUsesWith
// 步骤1: 处理所有使用者,将他们从使用 inst 变为使用 UndefinedValue
// 这将清理 inst 作为 Value 时的 uses 列表
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->replaceAllUsesWith(UndefinedValue::get(inst->getType()));
}
// 物理删除指令
inst->getParent()->removeInst(inst);
}
// 步骤2: 清理 inst 作为 User 时的操作数关系
// 通知 inst 所使用的所有 Value (如 AllocaInst),移除对应的 Use 关系。
// 这里的 inst 实际上是一个 User*,所以可以安全地向下转型。
RemoveUserOperandUses(static_cast<User*>(inst));
// 步骤3: 物理删除指令
// 这会导致 Instruction 对象的 unique_ptr 销毁,从而调用其析构函数链。
parentBlock->removeInst(inst);
}
static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) {
Instruction *inst_to_delete = inst_it->get();
BasicBlock *parentBlock = inst_to_delete->getParent();
assert(parentBlock && "Instruction must have a parent BasicBlock for iterator deletion.");
// 直接在此处执行 replaceAllUsesWith
// 步骤1: 处理所有使用者
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()));
inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType()));
}
// 物理删除指令
// 步骤2: 清理操作数关系
RemoveUserOperandUses(static_cast<User*>(inst_to_delete));
// 步骤3: 物理删除指令并返回下一个迭代器
return parentBlock->removeInst(inst_it);
}
}
// 判断是否是全局变量
static bool isGlobal(Value *val) {