|
|
|
|
@ -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);
|
|
|
|
|
|