fix(ir): CSE 扩展支持 LoadInst 和 GEPInst——修复 86_long_code2 编译超时

- ExprKey 从固定双操作数改为变长操作数向量,支持 Load/GEP/Binary
- IsCSECandidate 新增 Load 和 GEP 指令类型
- Store 指令失效对应地址的 Load 缓存,保证语义安全
- 86_long_code2: 编译从 >300s 超时降至 ~3s 完成,GEP+Load 从 8000 对降至 2 对
lzk
lzkk 5 days ago
parent 28ad162de4
commit 8f3012cd9f

@ -18,46 +18,42 @@ namespace ir {
namespace {
// 表达式的键:用于识别相同的表达式
// 表达式的键:用于识别相同的表达式(支持变长操作数)
struct ExprKey {
Opcode op;
Value* lhs;
Value* rhs;
std::vector<Value*> 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<int>()(static_cast<int>(key.op));
size_t h2 = std::hash<void*>()(key.lhs);
size_t h3 = std::hash<void*>()(key.rhs);
return h1 ^ (h2 << 1) ^ (h3 << 2);
size_t h = std::hash<int>()(static_cast<int>(key.op));
for (auto* op : key.operands)
h ^= std::hash<void*>()(op) + 0x9e3779b9 + (h << 6) + (h >> 2);
return h;
}
};
// 判断指令是否为可消除的公共子表达式
bool IsCSECandidate(Instruction* inst) {
// 只处理二元运算指令
if (auto* binary = dynamic_cast<BinaryInst*>(inst)) {
// 排除可能有副作用的运算(如除零)
// 这里保守处理:所有二元运算都可以作为候选
(void)binary; // 避免未使用变量警告
static bool IsCSECandidate(Instruction* inst) {
if (dynamic_cast<BinaryInst*>(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<BinaryInst*>(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);

Loading…
Cancel
Save