|
|
|
|
@ -58,11 +58,25 @@ static ExprKey GetExprKey(Instruction* inst) {
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
static int CountAllocas(Function &func) {
|
|
|
|
|
int count = 0;
|
|
|
|
|
for (auto &bb : func.GetBlocks())
|
|
|
|
|
for (auto &inst : bb->GetInstructions())
|
|
|
|
|
if (inst->GetOpcode() == Opcode::Alloca)
|
|
|
|
|
++count;
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RunCSE(Module& module) {
|
|
|
|
|
for (auto& func_ptr : module.GetFunctions()) {
|
|
|
|
|
auto* func = func_ptr.get();
|
|
|
|
|
if (func->IsExternal()) continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Mem2Reg 跳过的函数(大量 alloca),Load 可能访问不同作用域的同名变量,
|
|
|
|
|
// CSE 合并不同 Load 会破坏语义。此情况下仅对 BinaryInst 做 CSE。
|
|
|
|
|
int alloca_count = CountAllocas(*func);
|
|
|
|
|
bool cse_load_gep = (alloca_count <= 24);
|
|
|
|
|
|
|
|
|
|
// 对每个基本块执行 CSE
|
|
|
|
|
for (auto& bb_ptr : func->GetBlocks()) {
|
|
|
|
|
auto* bb = bb_ptr.get();
|
|
|
|
|
@ -97,8 +111,11 @@ void RunCSE(Module& module) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果是可消除的公共子表达式
|
|
|
|
|
if (IsCSECandidate(inst)) {
|
|
|
|
|
// 如果是可消除的公共子表达式(非 SSA 函数跳过 Load/GEP)
|
|
|
|
|
if (IsCSECandidate(inst) &&
|
|
|
|
|
(cse_load_gep ||
|
|
|
|
|
(inst->GetOpcode() != Opcode::Load &&
|
|
|
|
|
inst->GetOpcode() != Opcode::GEP))) {
|
|
|
|
|
ExprKey key = GetExprKey(inst);
|
|
|
|
|
|
|
|
|
|
// 检查是否已经计算过相同的表达式
|
|
|
|
|
|