[Mem2Reg]重构SSA提升

This commit is contained in:
rain2133
2025-07-18 18:17:45 +08:00
parent a5d97185e1
commit 34b5a93aaf
2 changed files with 535 additions and 774 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,57 +1,79 @@
#pragma once // 假设 Mem2Reg.h 看起来像这样 (你需要根据实际情况调整)
#ifndef SYSY_MEM2REG_H
#define SYSY_MEM2REG_H
#include <list> #include <vector>
#include <memory>
#include <stack>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <stack>
#include <queue> // For computeIteratedDomFrontiers
// Include your IR and analysis headers
#include "IR.h" #include "IR.h"
#include "IRBuilder.h" #include "IRBuilder.h"
#include "SysYIRAnalyser.h" #include "SysYIRAnalyser.h"
#include "SysYIROptUtils.h" #include "SysYIROptUtils.h"
namespace sysy { namespace sysy {
/**
* 实现静态单变量赋值核心类 mem2reg
*/
class Mem2Reg { class Mem2Reg {
private: private:
Module *pModule; Module* pModule;
IRBuilder *pBuilder; IRBuilder* pBuilder;
ControlFlowAnalysis *controlFlowAnalysis; // 控制流分析 ControlFlowAnalysis* controlFlowAnalysis;
ActiveVarAnalysis *activeVarAnalysis; // 活跃变量分析 ActiveVarAnalysis* activeVarAnalysis;
DataFlowAnalysisUtils dataFlowAnalysisUtils; DataFlowAnalysisUtils dataFlowAnalysisUtils; // If this is part of Mem2Reg or an external helper
public: public:
Mem2Reg(Module *pMoudle, IRBuilder *pBuilder, Mem2Reg(Module* module, IRBuilder* builder, ControlFlowAnalysis* cfa, ActiveVarAnalysis* ava)
ControlFlowAnalysis *pCFA = nullptr, ActiveVarAnalysis *pAVA = nullptr) : : pModule(module), pBuilder(builder), controlFlowAnalysis(cfa), activeVarAnalysis(ava) {}
pModule(pMoudle), pBuilder(pBuilder), controlFlowAnalysis(pCFA), activeVarAnalysis(pAVA), dataFlowAnalysisUtils() // Constructor initializes members
{} // 初始化函数 void run();
void mem2regPipeline(); ///< mem2reg // --- 新增的私有成员变量和方法用于SSA转换上下文 ---
// 这是核心,用于存储 SSA 转换过程中的状态
std::vector<AllocaInst*> currentFunctionAllocas; // 当前函数中所有可提升的 alloca
// alloca -> set of BasicBlocks where it's defined (stored into)
std::unordered_map<AllocaInst*, std::unordered_set<BasicBlock*>> allocaDefsBlock;
// alloca -> set of BasicBlocks where it's used (loaded from)
std::unordered_map<AllocaInst*, std::unordered_set<BasicBlock*>> allocaUsesBlock;
private: // BasicBlock -> Map of (PhiInst, Original AllocaInst)
// 用于在 rename 阶段通过 phi 指令找到它代表的原始 alloca
std::unordered_map<BasicBlock*, std::unordered_map<PhiInst*, AllocaInst*>> phiMap;
std::vector<PhiInst*> allPhiInstructions; // 收集所有创建的 Phi 指令以便后续简化和清理
// phi节点的插入需要计算IDF // --- 核心 SSA 转换辅助函数 ---
std::unordered_set<BasicBlock *> computeIterDf(const std::unordered_set<BasicBlock *> &blocks); ///< 计算定义块集合的迭代支配边界 // 计算给定定义块集合的迭代支配边界
std::unordered_set<BasicBlock*> computeIteratedDomFrontiers(const std::unordered_set<BasicBlock*>& blocks);
auto computeValue2Blocks() -> void; ///< 计算value2block的映射(不包括数组和global) // 分析一个 alloca 的所有 uses填充 allocaDefsBlock 和 allocaUsesBlock
void allocaAnalysis(AllocaInst* alloca);
auto preOptimize1() -> void; ///< llvm memtoreg预优化1: 删除不含load的alloc和store // 判断一个 alloca 是否可以被提升为寄存器 (无地址逃逸,标量类型)
auto preOptimize2() -> void; ///< llvm memtoreg预优化2: 针对某个变量的Defblocks只有一个块的情况 bool is_promoted(AllocaInst* alloca);
auto preOptimize3() -> void; ///< llvm memtoreg预优化3: 针对某个变量的所有读写都在同一个块中的情况
auto insertPhi() -> void; ///< 为所有变量的迭代支配边界插入phi结点 // 在迭代支配边界插入 Phi 指令
void insertPhiNodes(Function* func);
auto rename(BasicBlock *block, std::unordered_map<Value *, int> &count, // 递归地重命名基本块中的变量并填充 Phi 指令
std::unordered_map<Value *, std::stack<Instruction *>> &stacks) -> void; ///< 单个块的重命名 // 这里的 `count` 和 `stacks` 是临时的,用于 DFS 过程中传递状态
auto renameAll() -> void; ///< 重命名所有块 void renameBlock(BasicBlock* block,
std::unordered_map<AllocaInst*, Value*>& currentIncomings,
std::unordered_set<BasicBlock*>& visitedBlocks); // 修改为传递 map 和 set
// private helper function. // 简化冗余的 Phi 指令 (当所有输入都相同时)
private: void simplifyphi(PhiInst* phi);
auto getPredIndex(BasicBlock *n, BasicBlock *s) -> int; ///< 获取前驱索引
auto cascade(Instruction *instr, bool &changed, Function *func, BasicBlock *block, // 获取前驱块在后继块前驱列表中的索引,用于 Phi 指令入边
std::list<std::unique_ptr<Instruction>> &instrs) -> void; ///< 消除级联关系 int getPredIndex(BasicBlock* pred, BasicBlock* succ);
// --- Mem2Reg 的主要工作流函数 ---
// 对单个函数执行内存到寄存器的提升
bool promoteMemoryToRegisters(Function* func);
}; };
} // namespace sysy
} // namespace sysy
#endif // SYSY_MEM2REG_H