From ef09bc70d4e77d64213415084476fa3564f0dbc5 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 21:10:20 +0800 Subject: [PATCH] =?UTF-8?q?[midend]=E4=BF=AE=E6=94=B9=E4=BA=86removeinst?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E5=BA=94=E5=AF=B9=E4=B8=8D=E5=90=8C?= =?UTF-8?q?=E7=9A=84=E4=BD=BF=E7=94=A8=E6=83=85=E5=86=B5=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0user=E6=9E=90=E6=9E=84=E5=87=BD=E6=95=B0=E4=BD=BF?= =?UTF-8?q?=E5=BE=97user=E5=AF=B9=E8=B1=A1=E9=94=80=E6=AF=81=E9=A1=BA?= =?UTF-8?q?=E5=B8=A6=E9=94=80=E6=AF=81=E5=85=B6use=E5=85=B3=E7=B3=BB?= =?UTF-8?q?=E9=94=80=E6=AF=81=EF=BC=8C=E9=87=8D=E6=9E=84usedelete=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=B0=81=E8=A3=85=E6=8C=87=E4=BB=A4=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=92=8Cuse=E5=85=B3=E7=B3=BB=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/IR.h | 17 +++- .../midend/Pass/Optimize/SysYIROptUtils.h | 83 ++++++++++++++++--- 2 files changed, 86 insertions(+), 14 deletions(-) diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index 43a3a89..ab430f3 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -599,7 +599,7 @@ public: prev->addSuccessor(next); next->addPredecessor(prev); } - void removeInst(iterator pos) { instructions.erase(pos); } + iterator removeInst(iterator pos) { return instructions.erase(pos); } void removeInst(Instruction *inst) { auto pos = std::find_if(instructions.begin(), instructions.end(), [inst](const std::unique_ptr &i) { return i.get() == inst; }); @@ -626,6 +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>, + // 在此析构函数结束后,operands 向量会被销毁,其内部的 shared_ptr 也会被释放, + // 如果 shared_ptr 引用计数降为0,Use 对象本身也会被销毁。 + } unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量 auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器 auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器 diff --git a/src/include/midend/Pass/Optimize/SysYIROptUtils.h b/src/include/midend/Pass/Optimize/SysYIROptUtils.h index 1ee1ddc..a5a757d 100644 --- a/src/include/midend/Pass/Optimize/SysYIROptUtils.h +++ b/src/include/midend/Pass/Optimize/SysYIROptUtils.h @@ -22,23 +22,70 @@ public: } }; - // 仅仅删除use关系 - static void usedelete(Instruction *instr) { - for (auto &use : instr->getOperands()) { - Value* val = use->getValue(); - val->removeUse(use); + 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(); + 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())); } + // 至此,inst_to_delete 在语义上已不再被其他活跃指令使用。 } - // 删除use关系并删除指令 - static void usedelete_withinstdelte(Instruction *instr) { - for (auto &use : instr->getOperands()) { - Value* val = use->getValue(); - val->removeUse(use); - } - instr->getParent()->removeInst(instr); + // 版本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(); + + __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) 版本 + 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); @@ -47,7 +94,17 @@ public: // 判断是否是数组 static bool isArr(Value *val) { auto aval = dynamic_cast(val); - return aval != nullptr && aval->getNumDims() != 0; + // 如果是 AllocaInst 且通过Type::isArray()判断为数组类型 + return aval && aval->getType()->as()->getBaseType()->isArray(); + } + // 判断是否是指向数组的指针 + static bool isArrPointer(Value *val) { + auto aval = dynamic_cast(val); + // 如果是 AllocaInst 且通过Type::isPointer()判断为指针; + auto baseType = aval->getType()->as()->getBaseType(); + // 在sysy中,函数的数组参数会退化成指针 + // 所以当AllocaInst的basetype是PointerType时(一维数组)或者是指向ArrayType的PointerType(多位数组)时,返回true + return aval && (baseType->isPointer() || baseType->as()->getBaseType()->isArray()); } };