You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nudt-compiler-cpp/src/ir/passes/Mem2Reg.cpp

788 lines
26 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// Mem2RegSSA 构造):
// - 将局部变量的 alloca/load/store 提升为 SSA 形式
// - 使用标准的支配边界 + PHI 节点插入算法
#include "include/ir/IR.h"
#include <algorithm>
#include <iostream>
#include <map>
#include <memory>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace ir {
namespace {
constexpr bool kDebugMem2Reg = false;
// 计算基本块的后继
std::vector<BasicBlock*> GetSuccessors(BasicBlock* bb) {
std::vector<BasicBlock*> succs;
if (!bb) return succs;
auto& insts = bb->GetInstructions();
if (insts.empty()) return succs;
auto* term = insts.back().get();
if (!term) return succs;
switch (term->GetOpcode()) {
case Opcode::Br: {
auto* br = static_cast<BranchInst*>(term);
succs.push_back(br->GetTarget());
break;
}
case Opcode::CondBr: {
auto* cbr = static_cast<CondBranchInst*>(term);
succs.push_back(cbr->GetTrueTarget());
succs.push_back(cbr->GetFalseTarget());
break;
}
case Opcode::Ret:
break;
default:
break;
}
return succs;
}
// 计算基本块的前驱(通过扫描所有块的终止指令,不依赖缓存)
std::vector<BasicBlock*> GetPredecessors(BasicBlock* bb, Function* func = nullptr) {
std::vector<BasicBlock*> preds;
if (!bb || !func) return preds;
for (auto& block : func->GetBlocks()) {
auto succs = GetSuccessors(block.get());
for (auto* succ : succs) {
if (succ == bb) {
preds.push_back(block.get());
break;
}
}
}
return preds;
}
// 支配树相关信息
struct DominatorInfo {
std::unordered_map<BasicBlock*, BasicBlock*> idom;
std::unordered_map<BasicBlock*, std::vector<BasicBlock*>> dom_tree;
BasicBlock* entry = nullptr;
};
// 计算两个块的最近公共支配者
BasicBlock* Intersect(BasicBlock* b1, BasicBlock* b2,
const std::unordered_map<BasicBlock*, BasicBlock*>& idom) {
auto* finger1 = b1;
auto* finger2 = b2;
while (finger1 != finger2) {
while (finger1 && idom.count(finger1) && idom.at(finger1) && finger1 != idom.at(finger1)) {
finger1 = idom.at(finger1);
}
while (finger2 && idom.count(finger2) && idom.at(finger2) && finger2 != idom.at(finger2)) {
finger2 = idom.at(finger2);
}
if (finger1 == finger2) break;
if (finger1 && idom.count(finger1) && idom.at(finger1)) finger1 = idom.at(finger1);
if (finger2 && idom.count(finger2) && idom.at(finger2)) finger2 = idom.at(finger2);
}
return finger1;
}
// 预先计算所有块的支配者
DominatorInfo ComputeDominators(Function* func) {
DominatorInfo dom_info;
auto& blocks = func->GetBlocks();
if (blocks.empty()) return dom_info;
dom_info.entry = func->GetEntry();
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Computing dominators for function: " << func->GetName() << std::endl;
std::cerr << "[Mem2Reg] Entry block: " << dom_info.entry->GetName() << std::endl;
std::cerr << "[Mem2Reg] Total blocks: " << blocks.size() << std::endl;
// 调试前驱信息
for (auto& bb : blocks) {
auto preds = GetPredecessors(bb.get(), func);
std::cerr << " Block " << bb->GetName() << " has " << preds.size() << " predecessors: {";
bool first = true;
for (auto* pred : preds) {
if (!first) std::cerr << ", ";
std::cerr << pred->GetName();
first = false;
}
std::cerr << "}" << std::endl;
}
}
// 使用标准的迭代数据流算法计算支配者
// 初始化entry的idom是自己其他都是nullptr
for (auto& bb : blocks) {
dom_info.idom[bb.get()] = nullptr;
}
dom_info.idom[dom_info.entry] = dom_info.entry;
// 迭代直到收敛
bool changed = true;
int iteration = 0;
while (changed) {
changed = false;
++iteration;
if (iteration > 1000) {
std::cerr << "[Mem2Reg] ERROR: Dominator computation did not converge after 1000 iterations!" << std::endl;
break;
}
for (auto& bb : blocks) {
if (bb.get() == dom_info.entry) continue;
auto preds = GetPredecessors(bb.get(), func);
if (preds.empty()) continue;
// 找到第一个已经有idom的前驱
BasicBlock* new_idom = nullptr;
for (auto* pred : preds) {
if (dom_info.idom[pred] != nullptr) {
new_idom = pred;
break;
}
}
if (!new_idom) continue;
// 与其他有idom的前驱求交集
for (auto* pred : preds) {
if (pred == new_idom) continue;
if (dom_info.idom[pred] == nullptr) continue;
new_idom = Intersect(new_idom, pred, dom_info.idom);
if (!new_idom) break;
}
if (new_idom && dom_info.idom[bb.get()] != new_idom) {
dom_info.idom[bb.get()] = new_idom;
changed = true;
}
}
}
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Dominator computation completed after " << iteration << " iterations" << std::endl;
}
// 构建支配树
for (auto& bb : blocks) {
if (bb.get() == dom_info.entry) continue;
auto* idom = dom_info.idom[bb.get()];
if (idom && idom != bb.get()) {
dom_info.dom_tree[idom].push_back(bb.get());
}
}
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Dominator tree:" << std::endl;
int non_null_count = 0;
for (auto& bb : blocks) {
auto* idom = dom_info.idom[bb.get()];
if (idom) non_null_count++;
std::cerr << " " << bb->GetName() << " dominated by: "
<< (idom ? idom->GetName() : "null") << std::endl;
}
std::cerr << "[Mem2Reg] Blocks with non-null idom: " << non_null_count << "/" << blocks.size() << std::endl;
}
return dom_info;
}
// 计算支配边界
std::unordered_map<BasicBlock*, std::set<BasicBlock*>> ComputeDominanceFrontier(
Function* func, const DominatorInfo& dom_info) {
std::unordered_map<BasicBlock*, std::set<BasicBlock*>> df;
auto& blocks = func->GetBlocks();
for (auto& bb : blocks) {
df[bb.get()] = std::set<BasicBlock*>();
}
for (auto& bb : blocks) {
auto preds = GetPredecessors(bb.get(), func);
if (preds.size() < 2) continue;
auto* bb_idom = dom_info.idom.count(bb.get()) ? dom_info.idom.at(bb.get()) : nullptr;
if (!bb_idom) continue;
for (auto* pred : preds) {
auto* runner = pred;
while (runner != bb_idom) {
df[runner].insert(bb.get());
if (!runner || !dom_info.idom.count(runner) || !dom_info.idom.at(runner)) {
break;
}
auto* next = dom_info.idom.at(runner);
if (next == runner) break;
runner = next;
}
}
}
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Dominance frontiers:" << std::endl;
for (auto& bb : blocks) {
if (!df[bb.get()].empty()) {
std::cerr << " " << bb->GetName() << " -> {";
bool first = true;
for (auto* df_bb : df[bb.get()]) {
if (!first) std::cerr << ", ";
std::cerr << df_bb->GetName();
first = false;
}
std::cerr << "}" << std::endl;
}
}
}
return df;
}
// 检查是否是可以 SSA 化的 alloca
bool IsPromotableAlloca(AllocaInst* alloca) {
if (alloca->IsArrayAlloca()) {
return false;
}
auto uses = alloca->GetUses();
if (uses.empty()) {
return false; // 没有使用,不需要提升
}
bool has_load = false;
for (auto& use : uses) {
auto* user = use.GetUser();
if (!user) return false;
auto* inst = dynamic_cast<Instruction*>(user);
if (!inst) return false;
auto opcode = inst->GetOpcode();
if (opcode != Opcode::Load && opcode != Opcode::Store) {
return false;
}
if (opcode == Opcode::Store) {
auto* store = static_cast<StoreInst*>(inst);
if (store->GetPtr() != alloca) {
return false;
}
}
if (opcode == Opcode::Load) {
has_load = true;
}
}
return has_load; // 只有有 load 才需要提升
}
std::vector<AllocaInst*> FindPromotableAllocas(Function* func) {
std::vector<AllocaInst*> promotable;
// 扫描所有基本块中的 allocas不仅限于 entry 块)
for (auto& bb : func->GetBlocks()) {
for (auto& inst_ptr : bb->GetInstructions()) {
auto* inst = inst_ptr.get();
if (auto* alloca = dynamic_cast<AllocaInst*>(inst)) {
if (IsPromotableAlloca(alloca)) {
promotable.push_back(alloca);
}
}
}
}
if (kDebugMem2Reg && !promotable.empty()) {
std::cerr << "[Mem2Reg] Found " << promotable.size() << " promotable allocas in "
<< func->GetName() << std::endl;
for (auto* alloca : promotable) {
std::cerr << " - " << alloca->GetName() << std::endl;
}
}
return promotable;
}
// 插入 PHI 节点
void InsertPhiNodes(Function* func,
const std::vector<AllocaInst*>& allocas,
const DominatorInfo& dom_info,
const std::unordered_map<BasicBlock*, std::set<BasicBlock*>>& df,
std::unordered_map<AllocaInst*, std::unordered_map<BasicBlock*, PhiInst*>>& phi_nodes,
std::unordered_set<AllocaInst*>& skip_allocas) {
for (auto* alloca : allocas) {
std::set<BasicBlock*> store_blocks;
int store_count = 0;
for (auto& bb : func->GetBlocks()) {
for (auto& inst_ptr : bb->GetInstructions()) {
auto* inst = inst_ptr.get();
if (auto* store = dynamic_cast<StoreInst*>(inst)) {
if (store->GetPtr() == alloca) {
store_blocks.insert(bb.get());
store_count++;
}
}
}
}
if (kDebugMem2Reg && !store_blocks.empty()) {
std::cerr << "[Mem2Reg] Store blocks for " << alloca->GetName() << ": {";
bool first = true;
for (auto* bb : store_blocks) {
if (!first) std::cerr << ", ";
std::cerr << bb->GetName();
first = false;
}
std::cerr << "}" << std::endl;
}
std::set<BasicBlock*> phi_blocks;
std::vector<BasicBlock*> worklist(store_blocks.begin(), store_blocks.end());
std::set<BasicBlock*> visited(store_blocks.begin(), store_blocks.end());
while (!worklist.empty()) {
auto* bb = worklist.back();
worklist.pop_back();
auto df_it = df.find(bb);
if (df_it == df.end()) continue;
for (auto* df_block : df_it->second) {
if (phi_blocks.insert(df_block).second && visited.insert(df_block).second) {
worklist.push_back(df_block);
}
}
}
if (kDebugMem2Reg && !phi_blocks.empty()) {
std::cerr << "[Mem2Reg] PHI blocks for " << alloca->GetName() << ": {";
bool first = true;
for (auto* bb : phi_blocks) {
if (!first) std::cerr << ", ";
std::cerr << bb->GetName();
first = false;
}
std::cerr << "}" << std::endl;
}
if (store_count > 1 && !phi_blocks.empty()) {
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Alloca " << alloca->GetName()
<< " has multiple stores (store_count=" << store_count
<< ", phi_blocks=" << phi_blocks.size() << "), promoting anyway" << std::endl;
}
}
for (auto* bb : phi_blocks) {
auto& insts = const_cast<std::vector<std::unique_ptr<Instruction>>&>(bb->GetInstructions());
if (insts.empty()) continue;
// 使用 alloca 的元素类型作为 PHI 的类型
auto* phi = bb->Prepend<PhiInst>(alloca->GetElementType(), "");
phi->SetAlloca(alloca);
phi_nodes[alloca][bb] = phi;
}
}
}
// 全局 PHI 计数器
int gPhiCounter = 0;
// 重命名
void Rename(BasicBlock* bb,
const DominatorInfo& dom_info,
AllocaInst* alloca,
std::unordered_map<AllocaInst*, std::vector<Value*>>& value_stack,
std::unordered_map<AllocaInst*, std::unordered_map<BasicBlock*, PhiInst*>>& phi_nodes,
std::unordered_map<AllocaInst*, Value*>& initial_values) {
// 处理当前块的 PHI 节点
auto phi_it = phi_nodes.find(alloca);
if (phi_it != phi_nodes.end()) {
auto phi_block_it = phi_it->second.find(bb);
if (phi_block_it != phi_it->second.end()) {
auto* phi = phi_block_it->second;
// 给 PHI 节点一个名字
if (phi->GetName().empty()) {
phi->SetName("%phi" + std::to_string(gPhiCounter++));
}
value_stack[alloca].push_back(phi);
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Rename: Push PHI " << phi->GetName() << " for " << alloca->GetName()
<< " in block " << bb->GetName() << std::endl;
}
}
}
// 先处理指令store 推栈load 替换
for (auto& inst_ptr : bb->GetInstructions()) {
auto* inst = inst_ptr.get();
if (dynamic_cast<PhiInst*>(inst)) continue;
if (auto* store = dynamic_cast<StoreInst*>(inst)) {
if (store->GetPtr() == alloca) {
auto* val = store->GetValue();
value_stack[alloca].push_back(val);
// 记录初始值:第一个 store 的值作为初始值(覆盖默认值 0
// 这样可以正确处理循环不变量的情况
if (initial_values.count(alloca)) {
auto* current_init = initial_values[alloca];
// 如果当前初始值是默认值 0ConstantInt 0则更新为 store 的值
if (auto* const_int = dynamic_cast<ConstantInt*>(current_init)) {
if (const_int->GetValue() == 0) {
initial_values[alloca] = val;
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Rename: Update initial value for " << alloca->GetName()
<< " from 0 to " << val->GetName() << " in block " << bb->GetName() << std::endl;
}
}
}
} else {
initial_values[alloca] = val;
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Rename: Set initial value for " << alloca->GetName()
<< " to " << val->GetName() << " in block " << bb->GetName() << std::endl;
}
}
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Rename: Push store value " << val->GetName() << " for " << alloca->GetName()
<< " in block " << bb->GetName() << std::endl;
}
}
}
if (auto* load = dynamic_cast<LoadInst*>(inst)) {
if (load->GetPtr() == alloca) {
auto stack_it = value_stack.find(alloca);
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Checking load " << load->GetName() << " in " << bb->GetName()
<< ", stack size: " << (stack_it != value_stack.end() ? stack_it->second.size() : 0) << std::endl;
}
if (stack_it != value_stack.end() && !stack_it->second.empty()) {
auto* current_val = stack_it->second.back();
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Rename: Replacing load " << load->GetName()
<< " of " << alloca->GetName()
<< " in block " << bb->GetName()
<< " with value: " << (current_val ? current_val->GetName() : "null") << std::endl;
if (current_val && current_val->GetType()) {
std::cerr << "[Mem2Reg] Replacement value type: " << (int)current_val->GetType()->GetKind() << std::endl;
}
}
// 类型安全检查:确保替换值的类型与 load 的结果类型完全匹配
if (current_val && current_val->GetType()) {
auto* load_type = load->GetType().get();
auto* val_type = current_val->GetType().get();
if (load_type && val_type && load_type == val_type) {
load->ReplaceAllUsesWith(current_val);
} else {
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] WARNING: Type mismatch! Load type "
<< (load_type ? std::to_string((int)load_type->GetKind()) : "null")
<< " vs value type "
<< (val_type ? std::to_string((int)val_type->GetKind()) : "null") << std::endl;
}
}
}
} else {
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Rename: ERROR - Empty stack for load " << load->GetName()
<< " in block " << bb->GetName() << std::endl;
}
}
}
}
}
// 处理完指令后,填充后继块的 PHI 节点
auto successors = GetSuccessors(bb);
for (auto* succ : successors) {
auto succ_phi_it = phi_nodes.find(alloca);
if (succ_phi_it != phi_nodes.end()) {
auto succ_block_it = succ_phi_it->second.find(succ);
if (succ_block_it != succ_phi_it->second.end()) {
auto* phi = succ_block_it->second;
// 如果栈为空,使用初始值
Value* incoming_val = nullptr;
if (!value_stack[alloca].empty()) {
incoming_val = value_stack[alloca].back();
if (kDebugMem2Reg && incoming_val == phi) {
std::cerr << "[Mem2Reg] Rename: Self-referencing PHI in "
<< succ->GetName() << " for alloca " << alloca->GetName()
<< " (variable unchanged on this path)" << std::endl;
}
} else if (initial_values.count(alloca)) {
incoming_val = initial_values[alloca];
}
// 检查是否已经为这个前驱添加过条目
bool already_added = false;
for (size_t i = 1; i < phi->GetNumOperands(); i += 2) {
if (phi->GetOperand(i) == bb) {
already_added = true;
break;
}
}
if (!already_added && incoming_val) {
phi->AddOperand(incoming_val);
phi->AddOperand(bb);
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Rename: Adding operand to PHI in "
<< succ->GetName() << " from " << bb->GetName()
<< ", value: " << incoming_val->GetName() << std::endl;
}
} else if (!already_added && !incoming_val && kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Rename: WARNING - No value for PHI in "
<< succ->GetName() << " from " << bb->GetName() << std::endl;
}
}
}
}
// 递归处理支配树中的子块
auto dom_tree_it = dom_info.dom_tree.find(bb);
if (dom_tree_it != dom_info.dom_tree.end()) {
for (auto* child : dom_tree_it->second) {
Rename(child, dom_info, alloca, value_stack, phi_nodes, initial_values);
}
}
// 回溯
for (auto rit = bb->GetInstructions().rbegin(); rit != bb->GetInstructions().rend(); ++rit) {
auto* inst = rit->get();
if (dynamic_cast<PhiInst*>(inst)) continue;
if (auto* store = dynamic_cast<StoreInst*>(inst)) {
if (store->GetPtr() == alloca) {
auto& stack = value_stack[alloca];
if (!stack.empty()) {
stack.pop_back();
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Rename: Pop store value for " << alloca->GetName()
<< " in block " << bb->GetName() << std::endl;
}
}
}
}
}
// 弹出 PHI
auto phi_it2 = phi_nodes.find(alloca);
if (phi_it2 != phi_nodes.end()) {
auto phi_block_it = phi_it2->second.find(bb);
if (phi_block_it != phi_it2->second.end()) {
auto& stack = value_stack[alloca];
if (!stack.empty()) {
stack.pop_back();
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Rename: Pop PHI for " << alloca->GetName()
<< " in block " << bb->GetName() << std::endl;
}
}
}
}
}
// 删除冗余指令
void RemoveRedundantInstructions(Function* func, const std::vector<AllocaInst*>& allocas) {
std::set<Instruction*> to_delete;
std::set<AllocaInst*> alloca_set(allocas.begin(), allocas.end());
for (auto* alloca : allocas) {
to_delete.insert(alloca);
}
for (auto& bb : func->GetBlocks()) {
for (auto& inst_ptr : bb->GetInstructions()) {
auto* inst = inst_ptr.get();
if (auto* load = dynamic_cast<LoadInst*>(inst)) {
auto* ptr = load->GetPtr();
if (auto* alloca = dynamic_cast<AllocaInst*>(ptr)) {
if (alloca_set.count(alloca) && load->GetUses().empty()) {
to_delete.insert(load);
}
}
} else if (auto* store = dynamic_cast<StoreInst*>(inst)) {
auto* ptr = store->GetPtr();
if (auto* alloca = dynamic_cast<AllocaInst*>(ptr)) {
if (alloca_set.count(alloca)) {
to_delete.insert(store);
}
}
}
}
}
for (auto& bb : func->GetBlocks()) {
auto& insts = const_cast<std::vector<std::unique_ptr<Instruction>>&>(bb->GetInstructions());
for (auto it = insts.begin(); it != insts.end();) {
auto* inst = it->get();
if (to_delete.count(inst) && !dynamic_cast<AllocaInst*>(inst)) {
for (size_t i = 0; i < inst->GetNumOperands(); ++i) {
if (auto* op = inst->GetOperand(i)) {
auto& uses = const_cast<std::vector<Use>&>(op->GetUses());
uses.erase(
std::remove_if(uses.begin(), uses.end(),
[inst](const Use& use) { return use.GetUser() == inst; }),
uses.end());
}
}
it = insts.erase(it);
} else {
++it;
}
}
}
for (auto& bb : func->GetBlocks()) {
auto& insts = const_cast<std::vector<std::unique_ptr<Instruction>>&>(bb->GetInstructions());
for (auto it = insts.begin(); it != insts.end();) {
if (dynamic_cast<AllocaInst*>(it->get()) && to_delete.count(it->get())) {
auto* alloca = static_cast<AllocaInst*>(it->get());
auto& uses = const_cast<std::vector<Use>&>(alloca->GetUses());
uses.clear();
it = insts.erase(it);
} else {
++it;
}
}
}
}
} // anonymous namespace
// Mem2Reg 主函数
void RunMem2Reg(Module& module) {
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] === Starting Mem2Reg Pass ===" << std::endl;
}
for (auto& func_ptr : module.GetFunctions()) {
auto* func = func_ptr.get();
if (func->IsExternal()) continue;
// 跳过过大的函数以避免编译超时
if (func->GetBlocks().size() > 2000) {
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Skipping large function " << func->GetName()
<< " with " << func->GetBlocks().size() << " blocks" << std::endl;
}
continue;
}
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Processing function: " << func->GetName() << std::endl;
}
auto promotable_allocas = FindPromotableAllocas(func);
if (promotable_allocas.empty()) {
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] No promotable allocas in " << func->GetName() << std::endl;
}
continue;
}
auto dom_info = ComputeDominators(func);
auto df = ComputeDominanceFrontier(func, dom_info);
std::unordered_map<AllocaInst*, std::unordered_map<BasicBlock*, PhiInst*>> phi_nodes;
std::unordered_set<AllocaInst*> skip_allocas;
InsertPhiNodes(func, promotable_allocas, dom_info, df, phi_nodes, skip_allocas);
// 过滤掉需要跳过的 alloca
std::vector<AllocaInst*> filtered_allocas;
for (auto* alloca : promotable_allocas) {
if (skip_allocas.find(alloca) == skip_allocas.end()) {
filtered_allocas.push_back(alloca);
}
}
if (filtered_allocas.empty()) {
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] No promotable allocas left after filtering in " << func->GetName() << std::endl;
}
continue;
}
// 计算总 PHI 节点数量
int total_phi_count = 0;
for (auto& pair : phi_nodes) {
total_phi_count += pair.second.size();
}
// 启发式:如果 PHI 节点数量过多,跳过该函数
// PHI 节点在 llc -O0 下会生成 StoreStack 操作,可能导致性能下降
// 阈值设置:基本块数量的 1/4最小 10最大 30
int block_count = func->GetBlocks().size();
int phi_threshold = std::max(50, block_count);
if (total_phi_count > phi_threshold) {
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] Skipping function " << func->GetName()
<< " due to too many PHI nodes: " << total_phi_count
<< " (threshold: " << phi_threshold << ")" << std::endl;
}
continue;
}
for (auto* alloca : filtered_allocas) {
std::unordered_map<AllocaInst*, std::vector<Value*>> value_stack;
std::unordered_map<AllocaInst*, Value*> initial_values;
// 根据 alloca 的元素类型创建对应类型的默认常量 0
auto* elem_type = alloca->GetElementType().get();
Value* default_val = nullptr;
if (elem_type->IsInt32()) {
default_val = new ConstantInt(Type::GetInt32Type(), 0);
} else if (elem_type->IsInt1()) {
default_val = new ConstantInt(Type::GetInt1Type(), 0);
} else if (elem_type->IsFloat32()) {
default_val = new ConstantFloat(Type::GetFloat32Type(), 0.0);
}
if (default_val) {
initial_values[alloca] = default_val;
}
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] === Renaming for alloca: " << alloca->GetName() << " ===" << std::endl;
}
Rename(func->GetEntry(), dom_info, alloca, value_stack, phi_nodes, initial_values);
}
RemoveRedundantInstructions(func, filtered_allocas);
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] === Finished " << func->GetName() << " ===" << std::endl;
}
}
if (kDebugMem2Reg) {
std::cerr << "[Mem2Reg] === Mem2Reg Pass Complete ===" << std::endl;
}
}
} // namespace ir