119 lines
5.2 KiB
C++
119 lines
5.2 KiB
C++
#pragma once
|
||
|
||
#include "IR.h"
|
||
|
||
extern int DEBUG;
|
||
namespace sysy {
|
||
|
||
// 优化工具类,包含一些通用的优化方法
|
||
// 这些方法可以在不同的优化 pass 中复用
|
||
// 例如:删除use关系,判断是否是全局变量等
|
||
class SysYIROptUtils{
|
||
|
||
public:
|
||
struct PairHash {
|
||
template <class T1, class T2>
|
||
std::size_t operator () (const std::pair<T1, T2>& p) const {
|
||
auto h1 = std::hash<T1>{}(p.first);
|
||
auto h2 = std::hash<T2>{}(p.second);
|
||
|
||
// 简单的组合哈希值,可以更复杂以减少冲突
|
||
// 使用 boost::hash_combine 的简化版本
|
||
return h1 ^ (h2 << 1);
|
||
}
|
||
};
|
||
|
||
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.");
|
||
|
||
// 步骤1: 处理所有使用者,将他们从使用 inst 变为使用 UndefinedValue
|
||
// 这将清理 inst 作为 Value 时的 uses 列表
|
||
if (!inst->getUses().empty()) {
|
||
inst->replaceAllUsesWith(UndefinedValue::get(inst->getType()));
|
||
}
|
||
|
||
// 步骤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.");
|
||
|
||
// 步骤1: 处理所有使用者
|
||
if (!inst_to_delete->getUses().empty()) {
|
||
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) {
|
||
auto gval = dynamic_cast<GlobalValue *>(val);
|
||
return gval != nullptr;
|
||
}
|
||
// 判断是否是数组
|
||
static bool isArr(Value *val) {
|
||
auto aval = dynamic_cast<AllocaInst *>(val);
|
||
// 如果是 AllocaInst 且通过Type::isArray()判断为数组类型
|
||
return aval && aval->getType()->as<PointerType>()->getBaseType()->isArray();
|
||
}
|
||
// 判断是否是指向数组的指针
|
||
static bool isArrPointer(Value *val) {
|
||
auto aval = dynamic_cast<AllocaInst *>(val);
|
||
// 如果是 AllocaInst 且通过Type::isPointer()判断为指针;
|
||
auto baseType = aval->getType()->as<PointerType>()->getBaseType();
|
||
// 在sysy中,函数的数组参数会退化成指针
|
||
// 所以当AllocaInst的basetype是PointerType时(一维数组)或者是指向ArrayType的PointerType(多位数组)时,返回true
|
||
return aval && (baseType->isPointer() || baseType->as<PointerType>()->getBaseType()->isArray());
|
||
}
|
||
};
|
||
|
||
}// namespace sysy
|