Merge branch 'midend-mem2reg' into midend

This commit is contained in:
rain2133
2025-07-29 15:48:34 +08:00
14 changed files with 998 additions and 9 deletions

View File

@@ -16,17 +16,20 @@ public:
const std::set<BasicBlock*>* getDominators(BasicBlock* BB) const;
BasicBlock* getImmediateDominator(BasicBlock* BB) const;
const std::set<BasicBlock*>* getDominanceFrontier(BasicBlock* BB) const;
const std::set<BasicBlock*>* getDominatorTreeChildren(BasicBlock* BB) const;
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominatorsMap() const { return Dominators; }
const std::map<BasicBlock*, BasicBlock*>& getIDomsMap() const { return IDoms; }
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominanceFrontiersMap() const { return DominanceFrontiers; }
void computeDominators(Function* F);
void computeIDoms(Function* F);
void computeDominanceFrontiers(Function* F);
void computeDominatorTreeChildren(Function* F);
private:
Function* AssociatedFunction;
std::map<BasicBlock*, std::set<BasicBlock*>> Dominators;
std::map<BasicBlock*, BasicBlock*> IDoms;
std::map<BasicBlock*, std::set<BasicBlock*>> DominanceFrontiers;
std::map<BasicBlock*, std::set<BasicBlock*>> DominatorTreeChildren;
};

View File

@@ -525,6 +525,10 @@ public:
iterator begin() { return instructions.begin(); }
iterator end() { return instructions.end(); }
iterator terminator() { return std::prev(end()); }
iterator findInstIterator(Instruction *inst) {
return std::find_if(instructions.begin(), instructions.end(),
[inst](const std::unique_ptr<Instruction> &i) { return i.get() == inst; });
} ///< 查找指定指令的迭代器
bool hasSuccessor(BasicBlock *block) const {
return std::find(successors.begin(), successors.end(), block) != successors.end();
} ///< 判断是否有后继块
@@ -1112,7 +1116,10 @@ protected:
}
public:
//! 获取分配的类型
Type* getAllocatedType() const {
return getType()->as<PointerType>()->getBaseType();
} ///< 获取分配的类型
int getNumDims() const { return getNumOperands(); }
auto getDims() const { return getOperands(); }
Value* getDim(int index) { return getOperand(index); }

View File

@@ -294,7 +294,16 @@ class IRBuilder {
return inst;
} ///< 创建store指令
PhiInst * createPhiInst(Type *type, const std::vector<Value*> &vals = {}, const std::vector<BasicBlock*> &blks = {}, const std::string &name = "") {
auto inst = new PhiInst(type, vals, blks, block, name);
std::string newName;
if (name.empty()) {
std::stringstream ss;
ss << tmpIndex;
newName = ss.str();
tmpIndex++;
} else {
newName = name;
}
auto inst = new PhiInst(type, vals, blks, block, newName);
assert(inst);
block->getInstructions().emplace(block->begin(), inst);
return inst;

118
src/include/Mem2Reg.h Normal file
View File

@@ -0,0 +1,118 @@
#pragma once
#include "Pass.h" // 包含Pass的基类定义
#include "IR.h" // 包含IR相关的定义如Instruction, Function, BasicBlock, AllocaInst, LoadInst, StoreInst, PhiInst等
#include "Dom.h" // 假设支配树分析的头文件,提供 DominatorTreeAnalysisResult
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack> // 用于变量重命名阶段的SSA值栈
namespace sysy {
// 前向声明分析结果类,确保在需要时可以引用
class DominatorTree;
// Mem2RegContext 类,封装 mem2reg 遍的核心逻辑和状态
// 这样可以避免静态变量在多线程或多次运行时的冲突,并保持代码的模块化
class Mem2RegContext {
public:
Mem2RegContext(IRBuilder *builder) : builder(builder) {}
// 运行 mem2reg 优化的主要方法
// func: 当前要优化的函数
// tp: 分析管理器,用于获取支配树等分析结果
void run(Function* func, AnalysisManager* tp);
private:
IRBuilder *builder; // IR 构建器,用于插入指令
// 存储所有需要被提升的 AllocaInst
std::vector<AllocaInst*> promotableAllocas;
// 存储每个 AllocaInst 对应的 Phi 指令列表
// 键是 AllocaInst值是该 AllocaInst 在各个基本块中插入的 Phi 指令的列表
// (实际上,一个 AllocaInst 在一个基本块中只会有一个 Phi)
std::unordered_map<AllocaInst*, std::unordered_map<BasicBlock*, PhiInst*>> allocaToPhiMap;
// 存储每个 AllocaInst 对应的当前活跃 SSA 值栈
// 用于在变量重命名阶段追踪每个 AllocaInst 在不同控制流路径上的最新值
std::unordered_map<AllocaInst*, std::stack<Value*>> allocaToValueStackMap;
// 辅助映射,存储每个 AllocaInst 的所有 store 指令
std::unordered_map<AllocaInst*, std::unordered_set<StoreInst*>> allocaToStoresMap;
// 辅助映射,存储每个 AllocaInst 对应的定义基本块(包含 store 指令的块)
std::unordered_map<AllocaInst*, std::unordered_set<BasicBlock*>> allocaToDefBlocksMap;
// 支配树分析结果,用于 Phi 插入和变量重命名
DominatorTree* dt;
// --------------------------------------------------------------------
// 阶段1: 识别可提升的 AllocaInst
// --------------------------------------------------------------------
// 判断一个 AllocaInst 是否可以被提升到寄存器
// alloca: 要检查的 AllocaInst
// 返回值: 如果可以提升,则为 true否则为 false
bool isPromotableAlloca(AllocaInst* alloca);
// 收集所有对给定 AllocaInst 进行存储的 StoreInst
// alloca: 目标 AllocaInst
void collectStores(AllocaInst* alloca);
// --------------------------------------------------------------------
// 阶段2: 插入 Phi 指令 (Phi Insertion)
// --------------------------------------------------------------------
// 为给定的 AllocaInst 插入必要的 Phi 指令
// alloca: 目标 AllocaInst
// defBlocks: 包含对该 AllocaInst 进行 store 操作的基本块集合
void insertPhis(AllocaInst* alloca, const std::unordered_set<BasicBlock*>& defBlocks);
// --------------------------------------------------------------------
// 阶段3: 变量重命名 (Variable Renaming)
// --------------------------------------------------------------------
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
// alloca: 当前正在处理的 AllocaInst
// currentBB: 当前正在遍历的基本块
// dt: 支配树分析结果
// valueStack: 存储当前 AllocaInst 在当前路径上可见的 SSA 值栈
void renameVariables(AllocaInst* alloca, BasicBlock* currentBB);
// --------------------------------------------------------------------
// 阶段4: 清理
// --------------------------------------------------------------------
// 删除所有原始的 AllocaInst、LoadInst 和 StoreInst
void cleanup();
};
// Mem2Reg 优化遍类,继承自 OptimizationPass
// 粒度为 Function表示它在每个函数上独立运行
class Mem2Reg : public OptimizationPass {
private:
IRBuilder *builder;
public:
// 构造函数
Mem2Reg(IRBuilder *builder) : OptimizationPass("Mem2Reg", Granularity::Function), builder(builder) {}
// 静态成员作为该遍的唯一ID
static void *ID;
// 运行在函数上的优化逻辑
// F: 当前要优化的函数
// AM: 分析管理器,用于获取支配树等分析结果,或使分析结果失效
// 返回值: 如果IR被修改则为true否则为false
bool runOnFunction(Function *F, AnalysisManager& AM) override;
// 声明该遍的分析依赖和失效信息
// analysisDependencies: 该遍运行前需要哪些分析结果
// analysisInvalidations: 该遍运行后会使哪些分析结果失效
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
void *getPassID() const override { return &ID; }
};
} // namespace sysy

View File

@@ -11,6 +11,8 @@
#include "IR.h"
#include "IRBuilder.h"
extern int DEBUG; // 全局调试标志
namespace sysy {
//前向声明
@@ -149,6 +151,9 @@ public:
}
AnalysisPass *analysisPass = static_cast<AnalysisPass *>(basePass.get());
if(DEBUG){
std::cout << "Running Analysis Pass: " << analysisPass->getName() << "\n";
}
// 根据分析遍的粒度处理
switch (analysisPass->getGranularity()) {
case Pass::Granularity::Module: {
@@ -292,6 +297,9 @@ public:
AnalysisManager &getAnalysisManager() { return analysisManager; }
void clearPasses();
// 输出pass列表并打印IR信息供观察优化遍效果
void printPasses() const;
};
// ======================================================================

59
src/include/Reg2Mem.h Normal file
View File

@@ -0,0 +1,59 @@
#pragma once
#include "IR.h"
#include "IRBuilder.h" // 你的 IR Builder
#include "Liveness.h"
#include "Dom.h"
#include "Pass.h" // 你的 Pass 框架基类
#include <iostream> // 调试用
#include <map> // 用于 Value 到 AllocaInst 的映射
#include <set> // 可能用于其他辅助集合
#include <string>
#include <vector>
namespace sysy {
class Reg2MemContext {
public:
Reg2MemContext(IRBuilder *b) : builder(b) {}
// 运行 Reg2Mem 优化
void run(Function *func);
private:
IRBuilder *builder; // IR 构建器
// 存储 SSA Value 到对应的 AllocaInst 的映射
// 只有那些需要被"溢出"到内存的 SSA 值才会被记录在这里
std::map<Value *, AllocaInst *> valueToAllocaMap;
// 辅助函数:
// 1. 识别并为 SSA Value 分配 AllocaInst
void allocateMemoryForSSAValues(Function *func);
// 2. 将 SSA 值的使用替换为 Load/Store
void insertLoadsAndStores(Function *func);
// 3. 处理 Phi 指令,将其转换为 Load/Store
void rewritePhis(Function *func);
// 4. 清理 (例如,可能删除不再需要的 Phi 指令)
void cleanup(Function *func);
// 判断一个 Value 是否是 AllocaInst 可以为其分配内存的目标
// 通常指非指针类型的Instruction结果和Argument
bool isPromotableToMemory(Value *val);
};
class Reg2Mem : public OptimizationPass {
private:
IRBuilder *builder; ///< IR构建器用于插入指令
public:
static void *ID; ///< Pass的唯一标识符
Reg2Mem(IRBuilder* builder) : OptimizationPass("Reg2Mem", Pass::Granularity::Function), builder(builder) {}
bool runOnFunction(Function *F, AnalysisManager &AM) override;
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
void *getPassID() const override { return &ID; } ///< 获取 Pass ID
};
} // namespace sysy

View File

@@ -22,6 +22,8 @@ public:
static void printInst(Instruction *pInst);
static void printType(Type *type);
static void printValue(Value *value);
static void printBlock(BasicBlock *block);
static std::string getBlockName(BasicBlock *block);
static std::string getOperandName(Value *operand);
static std::string getTypeString(Type *type);
static std::string getValueName(Value *value);