[midend-mem2reg]dom增加访问支配树子节点求解和访问方法,修复block打印,phi指令命名,TODO:reg2membug待修复

This commit is contained in:
rain2133
2025-07-29 03:25:56 +08:00
parent 202e6d7cd8
commit 3dc4b28c92
8 changed files with 77 additions and 11 deletions

View File

@ -38,6 +38,14 @@ const std::set<BasicBlock *> *DominatorTree::getDominanceFrontier(BasicBlock *BB
return nullptr;
}
const std::set<BasicBlock*>* DominatorTree::getDominatorTreeChildren(BasicBlock* BB) const {
auto it = DominatorTreeChildren.find(BB);
if (it != DominatorTreeChildren.end()) {
return &(it->second);
}
return nullptr;
}
void DominatorTree::computeDominators(Function *F) {
// 经典的迭代算法计算支配者集合
// TODO: 可以替换为更高效的算法,如 Lengauer-Tarjan 算法
@ -159,6 +167,19 @@ void DominatorTree::computeDominanceFrontiers(Function *F) {
}
}
void DominatorTree::computeDominatorTreeChildren(Function *F) {
for (auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *B = bb_ptr.get();
auto it = getImmediateDominator(B);
if (it != nullptr) {
BasicBlock *A = it;
if (A) {
DominatorTreeChildren[A].insert(B);
}
}
}
}
// ==============================================================
// DominatorTreeAnalysisPass 的实现
// ==============================================================
@ -169,6 +190,7 @@ bool DominatorTreeAnalysisPass::runOnFunction(Function* F, AnalysisManager &AM)
CurrentDominatorTree->computeDominators(F);
CurrentDominatorTree->computeIDoms(F);
CurrentDominatorTree->computeDominanceFrontiers(F);
CurrentDominatorTree->computeDominatorTreeChildren(F);
return false;
}

View File

@ -193,7 +193,7 @@ void Mem2RegContext::insertPhis(AllocaInst *alloca, const std::unordered_set<Bas
// Phi 指令的类型与 alloca 的类型指向的类型相同
builder->setPosition(frontierBlock, frontierBlock->begin()); // 设置插入位置为基本块开头
auto phiInst = builder->createPhiInst(alloca->getAllocatedType(), {}, {frontierBlock}, "");
PhiInst *phiInst = builder->createPhiInst(alloca->getAllocatedType(), {}, {}, "");
allocaToPhiMap[alloca][frontierBlock] = phiInst; // 记录 Phi 指令
@ -294,12 +294,16 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr
// --------------------------------------------------------------------
// 递归访问支配树的子节点
// --------------------------------------------------------------------
const std::set<BasicBlock *> *dominatedBlocks = dt->getDominators(currentBB);
for (auto dominatedBB : *dominatedBlocks) {
if (dominatedBB) {
renameVariables(currentAlloca, dominatedBB);
const std::set<BasicBlock *> *dominatedBlocks = dt->getDominatorTreeChildren(currentBB);
if(dominatedBlocks){
for (auto dominatedBB : *dominatedBlocks) {
if (dominatedBB) {
std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() << std::endl;
renameVariables(currentAlloca, dominatedBB);
}
}
}
// --------------------------------------------------------------------
// 退出基本块时,弹出在此块中压入值栈的 SSA 值

View File

@ -1,6 +1,8 @@
#include "Reg2Mem.h"
#include "SysYIROptUtils.h" // 如果有的话
extern int DEBUG; // 全局调试标志
namespace sysy {
void *Reg2Mem::ID = (void *)&Reg2Mem::ID;
@ -30,6 +32,12 @@ void Reg2MemContext::run(Function *func) {
bool Reg2MemContext::isPromotableToMemory(Value *val) {
// 参数和指令结果是 SSA 值
if(DEBUG){
if(val->getName() == ""){
assert(false && "Value name should not be empty in Reg2MemContext::isPromotableToMemory");
}
std::cout << "Checking if value is promotable to memory: " << val->getName() << std::endl;
}
if (dynamic_cast<Argument *>(val) || dynamic_cast<Instruction *>(val)) {
// 如果值已经是指针类型,则通常不为其分配额外的内存,因为它已经是一个地址。
// (除非我们想将其值也存储起来,这通常不用于 Reg2Mem
@ -54,7 +62,7 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
for (auto arg : func->getArguments()) {
if (isPromotableToMemory(arg)) {
// 参数的类型就是 AllocaInst 需要分配的类型
AllocaInst *alloca = builder->createAllocaInst(arg->getType(), {}, arg->getName() + ".reg2mem");
AllocaInst *alloca = builder->createAllocaInst(arg->getType(), {});
// 将参数值 store 到 alloca 中 (这是 Mem2Reg 逆转的关键一步)
builder->createStoreInst(arg, alloca);
valueToAllocaMap[arg] = alloca;
@ -82,7 +90,7 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
// AllocaInst 应该在入口块,而不是当前指令所在块
// 这里我们只是创建,并稍后调整其位置
// 通常的做法是在循环结束后统一将 alloca 放到 entryBlock 的顶部
AllocaInst *alloca = builder->createAllocaInst(inst.get()->getType(), {}, inst->getName() + ".reg2mem");
AllocaInst *alloca = builder->createAllocaInst(inst.get()->getType(), {});
valueToAllocaMap[inst.get()] = alloca;
}
}

View File

@ -79,6 +79,15 @@ std::string SysYPrinter::getValueName(Value *value) {
return "";
}
std::string SysYPrinter::getBlockName(BasicBlock *block) {
static int blockId = 0; // 用于生成唯一的基本块ID
if (block->getName().empty()) {
return "bb" + std::to_string(blockId++); // 如果没有名字生成一个唯一的基本块ID
} else {
return block->getName();
}
}
void SysYPrinter::printType(Type *type) {
std::cout << getTypeString(type);
}
@ -128,6 +137,10 @@ void SysYPrinter::printGlobalVariable() {
}
}
void SysYPrinter::printBlock(BasicBlock *block) {
std::cout << getBlockName(block);
}
void SysYPrinter::printFunction(Function *function) {
// Function signature
std::cout << "define ";
@ -466,13 +479,13 @@ void SysYPrinter::printInst(Instruction *pInst) {
// 如果你的 PhiInst 存储方式是 getIncomingValues() 和 getIncomingBlocks(),请相应调整
// LLVM IR 格式: phi type [value1, block1], [value2, block2]
bool firstPair = true;
for (unsigned i = 0; i < phiInst->getNumOperands() / 2; ++i) { // 遍历成对的操作数
for (unsigned i = 0; i < phiInst->getNumIncomingValues(); ++i) { // 遍历成对的操作数
if (!firstPair) std::cout << ", ";
firstPair = false;
std::cout << "[ ";
printValue(phiInst->getOperand(i * 2)); // value
printValue(phiInst->getValue(i));
std::cout << ", %";
printValue(phiInst->getOperand(i * 2 + 1)); // block
printBlock(phiInst->getBlock(i));
std::cout << " ]";
}
std::cout << std::endl;

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

@ -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;

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: {

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);