// 公共子表达式消除(CSE): // - 识别并复用重复计算的等价表达式 // - 局部值编号:在单个基本块内消除重复计算 #include "ir/IR.h" #include #include #include #include namespace ir { namespace { // 为操作数生成唯一标识:常量使用值,否则使用指针 std::string ValKey(Value* v) { if (auto* ci = dynamic_cast(v)) return "ci" + std::to_string(ci->GetValue()); if (auto* cf = dynamic_cast(v)) { // 使用 IEEE 754 位表示 union { float f; uint32_t i; } u; u.f = cf->GetValue(); return "cf" + std::to_string(u.i); } // 非常量使用指针地址作为唯一标识 std::ostringstream oss; oss << "p" << reinterpret_cast(v); return oss.str(); } // 为可消除的指令生成 hash key std::string MakeKey(Instruction* inst) { switch (inst->GetOpcode()) { case Opcode::Add: case Opcode::Sub: case Opcode::Mul: case Opcode::Div: case Opcode::Mod: case Opcode::FAdd: case Opcode::FSub: case Opcode::FMul: case Opcode::FDiv: { auto* bin = static_cast(inst); return std::to_string(static_cast(inst->GetOpcode())) + "|" + ValKey(bin->GetLhs()) + "|" + ValKey(bin->GetRhs()); } case Opcode::ICmp: { auto* cmp = static_cast(inst); return std::to_string(static_cast(inst->GetOpcode())) + "|" + std::to_string(static_cast(cmp->GetPredicate())) + "|" + ValKey(cmp->GetLhs()) + "|" + ValKey(cmp->GetRhs()); } case Opcode::FCmp: { auto* cmp = static_cast(inst); return std::to_string(static_cast(inst->GetOpcode())) + "|" + std::to_string(static_cast(cmp->GetPredicate())) + "|" + ValKey(cmp->GetLhs()) + "|" + ValKey(cmp->GetRhs()); } case Opcode::Gep: { auto* gep = static_cast(inst); return std::to_string(static_cast(inst->GetOpcode())) + "|" + ValKey(gep->GetBasePtr()) + "|" + ValKey(gep->GetIndex()); } case Opcode::Load: { auto* ld = static_cast(inst); return std::to_string(static_cast(inst->GetOpcode())) + "|" + ValKey(ld->GetPtr()); } case Opcode::ZExt: { auto* ze = static_cast(inst); return std::to_string(static_cast(inst->GetOpcode())) + "|" + ValKey(ze->GetSrc()); } case Opcode::SIToFP: { auto* si = static_cast(inst); return std::to_string(static_cast(inst->GetOpcode())) + "|" + ValKey(si->GetSrc()); } case Opcode::FPToSI: { auto* fs = static_cast(inst); return std::to_string(static_cast(inst->GetOpcode())) + "|" + ValKey(fs->GetSrc()); } default: return ""; } } } // namespace bool RunCSE(Function& func) { bool changed = false; for (auto& bb : func.GetBlocks()) { std::unordered_map available; std::vector to_remove; for (auto& inst : bb->GetInstructions()) { auto* ip = inst.get(); std::string key = MakeKey(ip); if (key.empty()) { // 不可消除的指令:如果它有结果,可以考虑将其加入可用集 // 但为了简单,这里不处理 continue; } auto it = available.find(key); if (it != available.end()) { // 找到已有的等价指令,替换使用 ip->ReplaceAllUsesWith(it->second); to_remove.push_back(ip); changed = true; } else { available[key] = ip; } } for (auto* ip : to_remove) { for (size_t i = 0; i < ip->GetNumOperands(); ++i) ip->SetOperand(i, nullptr); ip->RemoveFromParent(); } } return changed; } } // namespace ir