diff --git a/src/ir/passes/CSE.cpp b/src/ir/passes/CSE.cpp index 1b4c67c6..0d7e4792 100644 --- a/src/ir/passes/CSE.cpp +++ b/src/ir/passes/CSE.cpp @@ -18,46 +18,42 @@ namespace ir { namespace { -// 表达式的键:用于识别相同的表达式 +// 表达式的键:用于识别相同的表达式(支持变长操作数) struct ExprKey { Opcode op; - Value* lhs; - Value* rhs; - + std::vector operands; + bool operator==(const ExprKey& other) const { - return op == other.op && lhs == other.lhs && rhs == other.rhs; + return op == other.op && operands == other.operands; } }; -// 为 ExprKey 提供哈希函数 struct ExprKeyHash { size_t operator()(const ExprKey& key) const { - size_t h1 = std::hash()(static_cast(key.op)); - size_t h2 = std::hash()(key.lhs); - size_t h3 = std::hash()(key.rhs); - return h1 ^ (h2 << 1) ^ (h3 << 2); + size_t h = std::hash()(static_cast(key.op)); + for (auto* op : key.operands) + h ^= std::hash()(op) + 0x9e3779b9 + (h << 6) + (h >> 2); + return h; } }; -// 判断指令是否为可消除的公共子表达式 -bool IsCSECandidate(Instruction* inst) { - // 只处理二元运算指令 - if (auto* binary = dynamic_cast(inst)) { - // 排除可能有副作用的运算(如除零) - // 这里保守处理:所有二元运算都可以作为候选 - (void)binary; // 避免未使用变量警告 +static bool IsCSECandidate(Instruction* inst) { + if (dynamic_cast(inst)) + return true; + // Load 和 GEP 也是纯计算,可消除重复 + if (inst->GetOpcode() == Opcode::Load) + return true; + if (inst->GetOpcode() == Opcode::GEP) return true; - } return false; } -// 获取表达式的键 -ExprKey GetExprKey(Instruction* inst) { - if (auto* binary = dynamic_cast(inst)) { - return ExprKey{binary->GetOpcode(), binary->GetLhs(), binary->GetRhs()}; - } - // 不应该到达这里 - return ExprKey{Opcode::Add, nullptr, nullptr}; +static ExprKey GetExprKey(Instruction* inst) { + ExprKey key; + key.op = inst->GetOpcode(); + for (size_t i = 0; i < inst->GetNumOperands(); ++i) + key.operands.push_back(inst->GetOperand(i)); + return key; } } // namespace @@ -83,7 +79,24 @@ void RunCSE(Module& module) { // 跳过 terminator 指令 if (inst->IsTerminator()) continue; - + + // Store 会修改内存——失效被 store 地址的 Load 缓存 + if (inst->GetOpcode() == Opcode::Store) { + // Store 操作数: [value, pointer] + if (inst->GetNumOperands() >= 2) { + Value* ptr = inst->GetOperand(1); + // 移除所有以该指针为操作数的 Load 缓存 + auto it = expr_table.begin(); + while (it != expr_table.end()) { + if (it->first.op == Opcode::Load && !it->first.operands.empty() && + it->first.operands[0] == ptr) + it = expr_table.erase(it); + else + ++it; + } + } + } + // 如果是可消除的公共子表达式 if (IsCSECandidate(inst)) { ExprKey key = GetExprKey(inst);