[midend]优化中端框架,移除无用旧代码,ignore格式文件

This commit is contained in:
rain2133
2025-07-22 21:25:07 +08:00
parent a72fc541fb
commit f61b51b2fa
14 changed files with 208 additions and 1220 deletions

3
.gitignore vendored
View File

@@ -53,4 +53,5 @@ __init__.py
.DS_*
antlr/
antlr/
.clang-format

View File

@@ -1,259 +0,0 @@
#include "DeadCodeElimination.h"
#include <iostream>
extern int DEBUG;
namespace sysy {
void DeadCodeElimination::runDCEPipeline() {
const auto& functions = pModule->getFunctions();
for (const auto& function : functions) {
const auto& func = function.second;
bool changed = true;
while (changed) {
changed = false;
eliminateDeadStores(func.get(), changed);
eliminateDeadLoads(func.get(), changed);
eliminateDeadAllocas(func.get(), changed);
eliminateDeadRedundantLoadStore(func.get(), changed);
eliminateDeadGlobals(changed);
}
}
}
// 消除无用存储 消除条件:
// 存储的目标指针pointer不是全局变量!isGlobal(pointer))。
// 存储的目标指针不是数组参数(!isArr(pointer) 或不在函数参数列表里)。
// 该指针的所有使用者uses仅限 alloca 或 store即没有 load 或其他指令使用它)。
void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) {
for (const auto& block : func->getBasicBlocks()) {
auto& instrs = block->getInstructions();
for (auto iter = instrs.begin(); iter != instrs.end();) {
auto inst = iter->get();
if (!inst->isStore()) {
++iter;
continue;
}
auto storeInst = dynamic_cast<StoreInst*>(inst);
auto pointer = storeInst->getPointer();
// 如果是全局变量或者是函数的数组参数
if (SysYIROptUtils::isGlobal(pointer) || (SysYIROptUtils::isArr(pointer) &&
std::find(func->getEntryBlock()->getArguments().begin(),
func->getEntryBlock()->getArguments().end(),
pointer) != func->getEntryBlock()->getArguments().end())) {
++iter;
continue;
}
bool changetag = true;
for (auto& use : pointer->getUses()) {
// 依次判断store的指针是否被其他指令使用
auto user = use->getUser();
auto userInst = dynamic_cast<Instruction*>(user);
// 如果使用store的指针的指令不是Alloca或Store则不删除
if (userInst != nullptr && !userInst->isAlloca() && !userInst->isStore()) {
changetag = false;
break;
}
}
if (changetag) {
changed = true;
if(DEBUG){
std::cout << "=== Dead Store Found ===\n";
SysYPrinter::printInst(storeInst);
}
SysYIROptUtils::usedelete(storeInst);
iter = instrs.erase(iter);
} else {
++iter;
}
}
}
}
// 消除无用加载 消除条件:
// 该指令的结果未被使用inst->getUses().empty())。
void DeadCodeElimination::eliminateDeadLoads(Function* func, bool& changed) {
for (const auto& block : func->getBasicBlocks()) {
auto& instrs = block->getInstructions();
for (auto iter = instrs.begin(); iter != instrs.end();) {
auto inst = iter->get();
if (inst->isBinary() || inst->isUnary() || inst->isLoad()) {
if (inst->getUses().empty()) {
changed = true;
if(DEBUG){
std::cout << "=== Dead Load Binary Unary Found ===\n";
SysYPrinter::printInst(inst);
}
SysYIROptUtils::usedelete(inst);
iter = instrs.erase(iter);
continue;
}
}
++iter;
}
}
}
// 消除无用加载 消除条件:
// 该 alloca 未被任何指令使用allocaInst->getUses().empty())。
// 该 alloca 不是函数的参数(不在 entry 块的参数列表里)。
void DeadCodeElimination::eliminateDeadAllocas(Function* func, bool& changed) {
for (const auto& block : func->getBasicBlocks()) {
auto& instrs = block->getInstructions();
for (auto iter = instrs.begin(); iter != instrs.end();) {
auto inst = iter->get();
if (inst->isAlloca()) {
auto allocaInst = dynamic_cast<AllocaInst*>(inst);
if (allocaInst->getUses().empty() &&
std::find(func->getEntryBlock()->getArguments().begin(),
func->getEntryBlock()->getArguments().end(),
allocaInst) == func->getEntryBlock()->getArguments().end()) {
changed = true;
if(DEBUG){
std::cout << "=== Dead Alloca Found ===\n";
SysYPrinter::printInst(inst);
}
SysYIROptUtils::usedelete(inst);
iter = instrs.erase(iter);
continue;
}
}
++iter;
}
}
}
void DeadCodeElimination::eliminateDeadIndirectiveAllocas(Function* func, bool& changed) {
// 删除mem2reg时引入的且现在已经没有value使用了的隐式alloca
FunctionAnalysisInfo* funcInfo = pCFA->getFunctionAnalysisInfo(func);
for (auto it = funcInfo->getIndirectAllocas().begin(); it != funcInfo->getIndirectAllocas().end();) {
auto &allocaInst = *it;
if (allocaInst->getUses().empty()) {
changed = true;
if(DEBUG){
std::cout << "=== Dead Indirect Alloca Found ===\n";
SysYPrinter::printInst(allocaInst.get());
}
it = funcInfo->getIndirectAllocas().erase(it);
} else {
++it;
}
}
}
// 该全局变量未被任何指令使用global->getUses().empty())。
void DeadCodeElimination::eliminateDeadGlobals(bool& changed) {
auto& globals = pModule->getGlobals();
for (auto it = globals.begin(); it != globals.end();) {
auto& global = *it;
if (global->getUses().empty()) {
changed = true;
if(DEBUG){
std::cout << "=== Dead Global Found ===\n";
SysYPrinter::printValue(global.get());
}
it = globals.erase(it);
} else {
++it;
}
}
}
// 消除冗余加载和存储 消除条件:
// phi 指令的目标指针仅被该 phi 使用(无其他 store/load 使用)。
// memset 指令的目标指针未被使用pointer->getUses().empty()
// store -> load -> store 模式
void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool& changed) {
for (const auto& block : func->getBasicBlocks()) {
auto& instrs = block->getInstructions();
for (auto iter = instrs.begin(); iter != instrs.end();) {
auto inst = iter->get();
if (inst->isPhi()) {
auto phiInst = dynamic_cast<PhiInst*>(inst);
auto pointer = phiInst->getPointer();
bool tag = true;
for (const auto& use : pointer->getUses()) {
auto user = use->getUser();
if (user != inst) {
tag = false;
break;
}
}
/// 如果 pointer 仅被该 phi 使用,可以删除 ph
if (tag) {
changed = true;
SysYIROptUtils::usedelete(inst);
iter = instrs.erase(iter);
continue;
}
// 数组指令还不完善不保证memset优化效果
} else if (inst->isMemset()) {
auto memsetInst = dynamic_cast<MemsetInst*>(inst);
auto pointer = memsetInst->getPointer();
if (pointer->getUses().empty()) {
changed = true;
SysYIROptUtils::usedelete(inst);
iter = instrs.erase(iter);
continue;
}
}else if(inst->isLoad()) {
if (iter != instrs.begin()) {
auto loadInst = dynamic_cast<LoadInst*>(inst);
auto loadPointer = loadInst->getPointer();
// TODO:store -> load -> store 模式
auto prevIter = std::prev(iter);
auto prevInst = prevIter->get();
if (prevInst->isStore()) {
auto prevStore = dynamic_cast<StoreInst*>(prevInst);
auto prevStorePointer = prevStore->getPointer();
auto prevStoreValue = prevStore->getOperand(0);
// 确保前一个 store 不是数组操作
if (prevStore->getIndices().empty()) {
// 检查后一条指令是否是 store 同一个值
auto nextIter = std::next(iter);
if (nextIter != instrs.end()) {
auto nextInst = nextIter->get();
if (nextInst->isStore()) {
auto nextStore = dynamic_cast<StoreInst*>(nextInst);
auto nextStorePointer = nextStore->getPointer();
auto nextStoreValue = nextStore->getOperand(0);
// 确保后一个 store 不是数组操作
if (nextStore->getIndices().empty()) {
// 判断优化条件:
// 1. prevStore 的指针操作数 == load 的指针操作数
// 2. nextStore 的值操作数 == load 指令本身
if (prevStorePointer == loadPointer &&
nextStoreValue == loadInst) {
// 可以优化直接把prevStorePointer的值存到nextStorePointer
changed = true;
nextStore->setOperand(0, prevStoreValue);
if(DEBUG){
std::cout << "=== Dead Store Load Store Found(now only del Load) ===\n";
SysYPrinter::printInst(prevStore);
SysYPrinter::printInst(loadInst);
SysYPrinter::printInst(nextStore);
}
SysYIROptUtils::usedelete(loadInst);
iter = instrs.erase(iter);
// 删除 prevStore 这里是不是可以留给删除无用store处理
// if (prevStore->getUses().empty()) {
// usedelete(prevStore);
// instrs.erase(prevIter); // 删除 prevStore
// }
continue; // 跳过 ++iter因为已经移动迭代器
}
}
}
}
}
}
}
}
++iter;
}
}
}
} // namespace sysy

View File

@@ -2,6 +2,7 @@
#include <algorithm> // For std::set_union, std::set_difference
#include <iostream>
#include <queue> // Potentially for worklist, though not strictly needed for the iterative approach below
#include <set> // For std::set
namespace sysy {
@@ -12,10 +13,6 @@ char LivenessAnalysisPass::ID = 0; // 任何唯一的地址都可以,这里用
// LivenessAnalysisResult 结果类的实现
// ==============================================================
LivenessAnalysisResult::LivenessAnalysisResult(Function *F) : AssociatedFunction(F) {
// 构造时可以不计算,在分析遍运行里计算并填充
}
const std::set<Value *> *LivenessAnalysisResult::getLiveIn(BasicBlock *BB) const {
auto it = liveInSets.find(BB);
if (it != liveInSets.end()) {
@@ -36,70 +33,83 @@ const std::set<Value *> *LivenessAnalysisResult::getLiveOut(BasicBlock *BB) cons
}
void LivenessAnalysisResult::computeDefUse(BasicBlock *BB, std::set<Value *> &def, std::set<Value *> &use) {
def.clear();
use.clear();
def.clear(); // 将持有在 BB 中定义的值
use.clear(); // 将持有在 BB 中使用但在其定义之前的值
// 临时集合,用于跟踪当前基本块中已经定义过的变量
std::set<Value *> defined_in_block_so_far;
// 按照指令在块中的顺序遍历
for (const auto &inst_ptr : BB->getInstructions()) {
Instruction *inst = inst_ptr.get();
// 检查指令是否产生值 (Def)
if (inst->hasValue()) { // 假设 Instruction 有 hasValue() 方法判断是否生成结果值
// 如果这个值在此指令之前在块中被使用过,则它是一个 Use
// 否则,它是 Def
if (use.find(inst) == use.end()) { // 如果当前指令本身的值未被当前块内之前的指令使用
def.insert(inst);
// 1. 处理指令的操作数 (Use) - 在定义之前的使用
for (const auto &use_ptr : inst->getOperands()) { // 修正迭代器类型
Value *operand = use_ptr->getValue(); // 从 shared_ptr<Use> 获取 Value*
// 过滤掉常量和全局变量,因为它们通常不被视为活跃变量
ConstantValue *constValue = dynamic_cast<ConstantValue *>(operand);
GlobalValue *globalValue = dynamic_cast<GlobalValue *>(operand);
if (constValue || globalValue) {
continue; // 跳过常量和全局变量
}
// 如果操作数是一个变量Instruction 或 Argument并且它在此基本块的当前点之前尚未被定义
if (defined_in_block_so_far.find(operand) == defined_in_block_so_far.end()) {
use.insert(operand);
}
}
// 检查指令的操作数 (Use)
for (Value *operand : inst->getOperands()) { // 假设 Instruction 有 getOperands() 返回 Value*
// 只有当操作数是一个Instruction或Argument且未在当前块中被定义时才算作 Use
if (auto opInst = dynamic_cast<Instruction *>(operand)) {
if (def.find(opInst) == def.end()) { // 如果操作数不是由当前块中之前的指令定义
use.insert(opInst);
}
} else if (auto arg = dynamic_cast<Argument *>(operand)) {
use.insert(arg);
}
// 常量和全局变量不计入 Def/Use 集合,因为它们不随控制流变化
// 2. 处理指令自身产生的定义 (Def)
if (inst->isDefine()) { // 使用 isDefine() 方法
// 指令自身定义了一个值。将其添加到块的 def 集合,
// 并添加到当前块中已定义的值的临时集合。
def.insert(inst); // inst 本身就是被定义的值(例如,虚拟寄存器)
defined_in_block_so_far.insert(inst);
}
}
}
void LivenessAnalysisResult::computeLiveness(Function *F) {
// 每次计算前清空旧结果
liveInSets[F].clear();
liveOutSets[F].clear();
liveInSets.clear(); // 直接清空 map不再使用 F 作为键
liveOutSets.clear(); // 直接清空 map
// 初始化所有基本块的 LiveIn 和 LiveOut 集合为空
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
liveInSets[F][bb] = {};
liveOutSets[F][bb] = {};
liveInSets[bb] = {}; // 直接以 bb 为键
liveOutSets[bb] = {}; // 直接以 bb 为键
}
bool changed = true;
while (changed) {
changed = false;
// 迭代所有基本块通常逆序遍历reverse post-order可以加快收敛
// 但为了简化,这里直接遍历所有块。
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
// TODO : 目前为逆序遍历基本块,考虑反向拓扑序遍历基本块
std::set<Value *> oldLiveIn = liveInSets[F][bb];
std::set<Value *> oldLiveOut = liveOutSets[F][bb];
// 逆序遍历基本块
std::list<std::unique_ptr<BasicBlock>> basicBlocks(F->getBasicBlocks().begin(), F->getBasicBlocks().end());
std::reverse(basicBlocks.begin(), basicBlocks.end());
// 然后遍历 basicBlocks
for (auto bb_iter = basicBlocks.begin(); bb_iter != basicBlocks.end(); ++bb_iter) {
BasicBlock *bb = bb_iter->get();
if (!bb)
continue; // 避免空指针
std::set<Value *> oldLiveIn = liveInSets[bb];
std::set<Value *> oldLiveOut = liveOutSets[bb];
// 1. 计算 LiveOut(BB) = Union(LiveIn(Succ) for Succ in Successors(BB))
std::set<Value *> newLiveOut;
for (BasicBlock *succ : bb->getSuccessors()) {
const std::set<Value *> *succLiveIn = getLiveIn(succ); // 递归获取后继的 LiveIn
const std::set<Value *> *succLiveIn = getLiveIn(succ); // 获取后继的 LiveIn
if (succLiveIn) {
newLiveOut.insert(succLiveIn->begin(), succLiveIn->end());
}
}
liveOutSets[F][bb] = newLiveOut;
liveOutSets[bb] = newLiveOut;
// 2. 计算 LiveIn(BB) = Use(BB) Union (LiveOut(BB) - Def(BB))
std::set<Value *> defSet, useSet;
@@ -111,7 +121,7 @@ void LivenessAnalysisResult::computeLiveness(Function *F) {
std::set<Value *> newLiveIn = useSet;
newLiveIn.insert(liveOutMinusDef.begin(), liveOutMinusDef.end());
liveInSets[F][bb] = newLiveIn;
liveInSets[bb] = newLiveIn;
// 检查是否发生变化
if (oldLiveIn != newLiveIn || oldLiveOut != newLiveOut) {
@@ -130,7 +140,6 @@ bool LivenessAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
CurrentLivenessResult = std::make_unique<LivenessAnalysisResult>(F);
// 调用 LivenessAnalysisResult 内部的方法来计算分析结果
// 这里的 computeLiveness 不需要 AM 参数,因为它自身不依赖其他分析。
CurrentLivenessResult->computeLiveness(F);
// 分析遍通常不修改 IR所以返回 false

View File

@@ -1,515 +0,0 @@
#include "Mem2Reg.h"
#include "SysYIRPrinter.h"
#include <algorithm>
#include <cassert>
#include <memory>
#include <queue>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace sysy {
// --- 私有成员函数实现 ---
// 计算给定定义块集合的迭代支配边界
std::unordered_set<BasicBlock*> Mem2Reg::computeIteratedDomFrontiers(const std::unordered_set<BasicBlock*>& blocks) {
std::unordered_set<BasicBlock*> result;
std::queue<BasicBlock*> worklist; // 使用队列进行 BFS-like 遍历
for (auto* block : blocks)
worklist.push(block);
while (!worklist.empty()) {
auto* block = worklist.front();
worklist.pop();
auto* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(block);
if (!blockInfo) continue;
for (auto* df : blockInfo->getDomFrontiers()) {
if (result.find(df) == result.end()) { // If not already in result
result.insert(df);
worklist.push(df);
}
}
}
return result;
}
// 分析一个 alloca 的所有 uses填充 allocaDefsBlock 和 allocaUsesBlock
void Mem2Reg::allocaAnalysis(AllocaInst* alloca) {
allocaDefsBlock[alloca].clear();
allocaUsesBlock[alloca].clear();
for (auto use : alloca->getUses()) {
Instruction* userInst = dynamic_cast<Instruction*>(use->getUser());
if (!userInst) continue;
if (StoreInst* store = dynamic_cast<StoreInst*>(userInst)) {
if (store->getOperand(1) == alloca) { // Store's second operand is the pointer
allocaDefsBlock[alloca].insert(store->getParent()); // Store's parent is the defining block
}
} else if (LoadInst* load = dynamic_cast<LoadInst*>(userInst)) {
if (load->getOperand(0) == alloca) { // Load's first operand is the pointer
allocaUsesBlock[alloca].insert(load->getParent()); // Load's parent is the using block
}
}
}
}
// 判断一个 alloca 是否可以被提升为寄存器 (无地址逃逸,标量类型)
bool Mem2Reg::is_promoted(AllocaInst* alloca) {
// 检查是否是标量类型 (非数组、非全局变量等)
if(!(SysYIROptUtils::isArr(alloca) || SysYIROptUtils::isGlobal(alloca))){
return false; // 只有标量类型的 alloca 才能被提升
}
// 获取 alloca 指向的基类型
PointerType* ptrType = dynamic_cast<PointerType*>(alloca->getType());
if (!ptrType) return false; // Should always be a pointer type
Type* allocabaseType = ptrType->getBaseType();
for (const auto& use : alloca->getUses()) {
Instruction* userInst = dynamic_cast<Instruction*>(use->getUser());
if (!userInst) {
// 如果不是指令的 use比如作为全局变量的初始值等通常认为逃逸
return false;
}
if (LoadInst* load = dynamic_cast<LoadInst*>(userInst)) {
// Load 指令结果的类型必须与 alloca 的基类型一致
if (load->getType() != allocabaseType) {
return false;
}
} else if (StoreInst* store = dynamic_cast<StoreInst*>(userInst)) {
// Store 指令的值操作数类型必须与 alloca 的基类型一致
// 且 store 的指针操作数必须是当前 alloca
if (store->getOperand(1) != alloca || store->getOperand(0)->getType() != allocabaseType) {
return false;
}
} else if (userInst->isGetSubArray()) {
// GSA 指令表示对数组的访问
// 这意味着地址逃逸,不能简单提升为单个寄存器
return false;
} else if (userInst->isCall()) {
// 如果 alloca 作为函数参数传递,通常认为地址逃逸
return false;
}
// 如果有其他类型的指令使用 alloca 的地址,也需要判断是否是逃逸
// 例如BitCastInst, PtrToIntInst, 如果这些操作将地址暴露,则不能提升
}
return true;
}
// 在迭代支配边界处插入 Phi 指令
void Mem2Reg::insertPhiNodes(Function* func) {
// 清空上次 Phi 插入的结果
phiMap.clear();
allPhiInstructions.clear();
std::unordered_set<BasicBlock*> phiPlacementBlocks; // 存放需要插入 Phi 的块
std::queue<BasicBlock*> workQueue; // BFS 队列,用于迭代支配边界计算
// 遍历所有可提升的 alloca
for (AllocaInst* alloca : currentFunctionAllocas) {
phiPlacementBlocks.clear(); // 为每个 alloca 重新计算 Phi 放置位置
// 初始化工作队列,放入所有定义该 alloca 的基本块
for (BasicBlock* defBB : allocaDefsBlock[alloca]) {
workQueue.push(defBB);
}
while (!workQueue.empty()) {
BasicBlock* currentBB = workQueue.front();
workQueue.pop();
auto* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(currentBB);
if (!blockInfo) continue;
// 遍历当前块的支配边界
for (BasicBlock* domFrontierBB : blockInfo->getDomFrontiers()) {
// 如果这个支配边界块还没有为当前 alloca 插入 Phi 指令
if (phiPlacementBlocks.find(domFrontierBB) == phiPlacementBlocks.end()) {
// 获取 alloca 的基类型,作为 Phi 指令的结果类型
Type* phiType = dynamic_cast<PointerType*>(alloca->getType())->getBaseType();
// 在支配边界块的开头插入 Phi 指令
pBuilder->setPosition(domFrontierBB->begin());
PhiInst* newPhi = pBuilder->createPhiInst(phiType, {}, {}); // 初始入边为空
allPhiInstructions.push_back(newPhi); // 记录所有 Phi
phiPlacementBlocks.insert(domFrontierBB); // 标记已插入
// 将 Phi 指令映射到它所代表的原始 alloca
phiMap[domFrontierBB][newPhi] = alloca;
// 如果支配边界块本身没有定义该 alloca则其支配边界也可能需要 Phi
// 只有当这个块不是当前alloca的定义块时才将其加入workQueue以计算其DF。
if (allocaDefsBlock[alloca].find(domFrontierBB) == allocaDefsBlock[alloca].end()) {
workQueue.push(domFrontierBB);
}
}
}
}
}
}
// 获取前驱块在后继块前驱列表中的索引
int Mem2Reg::getPredIndex(BasicBlock* pred, BasicBlock* succ) {
int index = 0;
for (auto* elem : succ->getPredecessors()) {
if (elem == pred) {
return index;
}
++index;
}
// 断言通常在你的 IR 框架中应该确保前驱是存在的
// assert(false && "Predecessor not found in successor's predecessor list");
return -1; // 应该不会发生
}
// 递归地重命名基本块中的变量并填充 Phi 指令
void Mem2Reg::renameBlock(BasicBlock* block,
std::unordered_map<AllocaInst*, Value*>& currentIncomings,
std::unordered_set<BasicBlock*>& visitedBlocks) {
// 记录在此块中发生的定义,以便在退出时将它们从栈中弹出
std::unordered_map<AllocaInst*, int> definitionsInBlockCount;
// 如果已经访问过这个块直接返回防止无限循环或重复处理在DFS中尤其重要
if (visitedBlocks.count(block)) {
return;
}
visitedBlocks.insert(block);
// --- 1. 处理当前基本块内的指令 ---
// 使用迭代器安全地遍历和删除指令
for (auto it = block->getInstructions().begin(); it != block->getInstructions().end(); ) {
Instruction* currentInst = it->get();
if (AllocaInst* alloca = dynamic_cast<AllocaInst*>(currentInst)) {
// 如果是可提升的 alloca标记为删除
if (std::find(currentFunctionAllocas.begin(), currentFunctionAllocas.end(), alloca) != currentFunctionAllocas.end()) {
SysYIROptUtils::usedelete(currentInst); // 标记为删除(或直接删除取决于你的 IR 管理)
it = block->getInstructions().erase(it); // 从列表中移除
continue; // 继续下一个指令
}
} else if (LoadInst* load = dynamic_cast<LoadInst*>(currentInst)) {
AllocaInst* originalAlloca = dynamic_cast<AllocaInst*>(load->getOperand(0)); // load 的第一个操作数是指针
if (originalAlloca && std::find(currentFunctionAllocas.begin(), currentFunctionAllocas.end(), originalAlloca) != currentFunctionAllocas.end()) {
// 如果是可提升 alloca 的 load 指令
Value* incomingVal = nullptr;
if (currentIncomings.count(originalAlloca)) {
incomingVal = currentIncomings[originalAlloca];
} else {
// 如果在当前路径上没有找到定义,则使用 UndefinedValue
incomingVal = UndefinedValue::get(originalAlloca->getType()->isPointer() ?
dynamic_cast<PointerType*>(originalAlloca->getType())->getBaseType() :
originalAlloca->getType());
}
load->replaceAllUsesWith(incomingVal); // 用最新值替换所有 load 的用途
SysYIROptUtils::usedelete(currentInst);
it = block->getInstructions().erase(it);
continue;
}
} else if (StoreInst* store = dynamic_cast<StoreInst*>(currentInst)) {
AllocaInst* originalAlloca = dynamic_cast<AllocaInst*>(store->getOperand(1)); // store 的第二个操作数是指针
if (originalAlloca && std::find(currentFunctionAllocas.begin(), currentFunctionAllocas.end(), originalAlloca) != currentFunctionAllocas.end()) {
// 如果是可提升 alloca 的 store 指令,更新当前值
currentIncomings[originalAlloca] = store->getOperand(0); // store 的第一个操作数是值
definitionsInBlockCount[originalAlloca]++; // 记录在该块中进行的定义数量
SysYIROptUtils::usedelete(currentInst);
it = block->getInstructions().erase(it);
continue;
}
} else if (PhiInst* phi = dynamic_cast<PhiInst*>(currentInst)) {
// 如果是 Mem2Reg 插入的 Phi 指令 (通过 phiMap 判断)
if (phiMap[block].count(phi)) {
AllocaInst* originalAlloca = phiMap[block][phi];
currentIncomings[originalAlloca] = phi; // Phi 指令本身成为该变量的新定义
definitionsInBlockCount[originalAlloca]++; // 记录该 Phi 的定义
}
}
++it; // 移动到下一个指令
}
// --- 2. 填充后继基本块中 Phi 指令的入边 ---
for (BasicBlock* successorBB : block->getSuccessors()) {
int predIndex = getPredIndex(block, successorBB);
if (predIndex == -1) continue;
// Phi 指令总是在基本块的开头
for (auto& inst_ptr : successorBB->getInstructions()) {
if (PhiInst* phi = dynamic_cast<PhiInst*>(inst_ptr.get())) {
if (phiMap[successorBB].count(phi)) { // 确保这是我们关心的 Phi 指令
AllocaInst* originalAlloca = phiMap[successorBB][phi];
Value* incomingValue = nullptr;
if (currentIncomings.count(originalAlloca)) {
incomingValue = currentIncomings[originalAlloca];
} else {
// 如果在当前块没有找到对应的定义,使用 UndefinedValue
incomingValue = UndefinedValue::get(originalAlloca->getType()->isPointer() ?
dynamic_cast<PointerType*>(originalAlloca->getType())->getBaseType() :
originalAlloca->getType());
}
if (incomingValue) {
phi->addIncoming(incomingValue, block); // 添加 (值, 前驱块) 对
}
}
} else {
// 遇到非 Phi 指令,说明已经处理完所有 Phi可以跳出
break;
}
}
}
// --- 3. 递归调用支配树的子节点 ---
auto* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(block);
if (blockInfo) {
for (BasicBlock* dominatedChildBB : blockInfo->getSdoms()) { // getSdoms 获取直接支配的子节点
// 递归调用,传递当前 Incomings 的副本(或通过值传递以实现回溯)
// 注意:这里是传递 `currentIncomings` 的拷贝,以便递归返回后可以恢复。
// 但如果 `currentIncomings` 是引用传递,则这里需要回溯逻辑。
// 鉴于它是值传递,此处的 `definitionsInBlockCount` 仅用于统计,无需实际操作 `currentIncomings`。
renameBlock(dominatedChildBB, currentIncomings, visitedBlocks);
}
}
// --- 4. 回溯:从栈中弹出在此块中创建的所有定义 ---
for (auto const& [alloca, count] : definitionsInBlockCount) {
// 在我们的实现中,`currentIncomings` 是通过值传递的,每次递归都收到一个新的拷贝。
// 因此,不需要显式地 "pop" 栈。`currentIncomings` 在函数返回时会自动销毁。
// 这种方式模拟了 "SSA 栈" 的行为,每个函数调用帧有自己的局部定义环境。
}
}
// 简化冗余的 Phi 指令 (当所有输入都相同时)
void Mem2Reg::simplifyphi(PhiInst* phi) {
BasicBlock* phifromblock = phi->getParent();
if (!phifromblock) return; // 指令可能已经被删除
Value* commonValue = nullptr;
bool allSame = true;
// Phi 指令的操作数是 Value, BasicBlock 交替出现,所以是 getOperandSize() / 2 个入边
if (phi->getNumOperands() == 0) { // 空 Phi通常是无效的直接删除
phi->replaceAllUsesWith(UndefinedValue::get(phi->getType())); // 用 UndefinedValue 替换所有用途
// phi->getParent()->delete_inst(phi);
// 删除 Phi 指令后直接返回
// phi指令在开头一个比较快
// TODO后续可优化查找
auto tofind = std::find_if(phifromblock->getInstructions().begin(), phifromblock->getInstructions().end(),
[phi](const auto &instr) { return instr.get() == phi; });
SysYIROptUtils::usedelete(phi); // 使用 SysYIROptUtils 删除指令
phifromblock->getInstructions().erase(tofind);
// 从基本块中删除 Phi 指令
return;
}
for (size_t i = 0; i < phi->getNumIncomingValues(); ++i) {
Value* incomingVal = phi->getOperand(2 * i); // 值位于偶数索引
if (incomingVal == phi) { // 如果 Phi 指令引用自身 (循环变量)
// 这种情况下Phi 暂时不能简化,除非所有入边都是它自己,这通常通过其他优化处理
// 为避免复杂性,我们在此处不处理自引用 Phi 的简化,除非它是唯一选择。
// 更好的做法是如果所有入边都指向自身则该Phi是冗余的可以替换为undef或其第一个实际值
// 但这需要更复杂的分析来确定循环的初始值。目前简单返回。
// TODO留到后续循环优化处理
return;
}
if (commonValue == nullptr) {
commonValue = incomingVal;
} else if (commonValue != incomingVal) {
allSame = false;
break; // 发现不同的入边值
}
}
if (allSame && commonValue != nullptr) {
// 所有入边值都相同,用这个值替换 Phi 指令的所有用途
phi->replaceAllUsesWith(commonValue);
// 从基本块中删除 Phi 指令
auto tofind = std::find_if(phifromblock->getInstructions().begin(), phifromblock->getInstructions().end(),
[phi](const auto &instr) { return instr.get() == phi; });
SysYIROptUtils::usedelete(phi); // 使用 SysYIROptUtils 删除指令
phifromblock->getInstructions().erase(tofind);
}
}
// 对单个函数执行内存到寄存器的提升
bool Mem2Reg::promoteMemoryToRegisters(Function* func) {
bool changed = false;
// 每次开始对一个函数进行 Mem2Reg 时,清空所有上下文信息
currentFunctionAllocas.clear();
allocaDefsBlock.clear();
allocaUsesBlock.clear();
phiMap.clear();
allPhiInstructions.clear();
// 1. 收集所有可提升的 AllocaInst并进行初步分析
BasicBlock* entryBB = func->getEntryBlock();
if (!entryBB) return false;
// 逆序遍历入口块的指令,安全地识别 Alloca
for (auto it = entryBB->getInstructions().rbegin(); it != entryBB->getInstructions().rend(); ++it) {
if (AllocaInst* alloca = dynamic_cast<AllocaInst*>(it->get())) {
if (is_promoted(alloca)) {
currentFunctionAllocas.push_back(alloca);
}
}
}
// 收集后反转,使其按原始顺序排列 (如果需要的话,但对后续分析影响不大)
std::reverse(currentFunctionAllocas.begin(), currentFunctionAllocas.end());
// 对收集到的所有 alloca 进行 DefsBlock 和 UsesBlock 分析
for (AllocaInst* alloca : currentFunctionAllocas) {
allocaAnalysis(alloca);
}
// 2. 预处理:删除无用的 AllocaInst (没有 Load 和 Store)
// 迭代 currentFunctionAllocas安全删除
for (unsigned int i = 0; i < currentFunctionAllocas.size(); ) {
AllocaInst* alloca = currentFunctionAllocas[i];
bool hasRelevantUse = false;
// 检查 alloca 的 uses 列表,看是否有 Load 或 Store
// 只要有 Load/Store就认为是"相关用途",不删除
for (auto use_ptr : alloca->getUses()) {
Instruction* user_inst = dynamic_cast<Instruction*>(use_ptr->getUser());
if (user_inst && (dynamic_cast<LoadInst*>(user_inst) || dynamic_cast<StoreInst*>(user_inst))) {
hasRelevantUse = true;
break;
}
}
// 如果没有相关用途(没有 Load 和 Store则 alloca 是死代码
if (!hasRelevantUse && allocaDefsBlock[alloca].empty() && allocaUsesBlock[alloca].empty()) {
if (alloca->getParent()) {
// alloca->getParent()->delete_inst(alloca); // 从其所在块删除 alloca 指令
auto tofind = std::find_if(alloca->getParent()->getInstructions().begin(), alloca->getParent()->getInstructions().end(),
[alloca](const auto &instr) { return instr.get() == alloca; });
SysYIROptUtils::usedelete(alloca);
alloca->getParent()->getInstructions().erase(tofind);
}
currentFunctionAllocas.erase(currentFunctionAllocas.begin() + i); // 从列表中移除
changed = true; // 发生了改变
} else {
i++; // 否则,移动到下一个 alloca
}
}
// 如果没有可提升的 alloca 了,直接返回
if (currentFunctionAllocas.empty()) {
return changed;
}
// 3. 插入 Phi 指令
insertPhiNodes(func);
if (!allPhiInstructions.empty()) changed = true;
// 4. 重命名变量,转换为 SSA 形式并填充 Phi 指令
std::unordered_map<AllocaInst*, Value*> initialIncomings;
std::unordered_set<BasicBlock*> visitedBlocks; // 用于 DFS 遍历,防止循环
// 初始化 entry block 的 Incomings 状态
for (AllocaInst* alloca : currentFunctionAllocas) {
initialIncomings[alloca] = UndefinedValue::get(dynamic_cast<PointerType*>(alloca->getType())->getBaseType());
}
// 从入口块开始递归重命名
renameBlock(entryBB, initialIncomings, visitedBlocks);
// 5. 简化 Phi 指令
// 由于 renameBlock 可能会删除 Phi这里复制一份列表以安全迭代
std::vector<PhiInst*> phisToSimplify = allPhiInstructions;
for (PhiInst* phi : phisToSimplify) {
// 检查 phi 是否还在 IR 中 (可能已被其他优化删除)
// 一个简单检查是看它是否有父块
if (phi->getParent()) {
simplifyphi(phi);
// simplifyphi 内部会删除 Phi所以这里不需要再处理 allPhiInstructions
// 最终的 allPhiInstructions 清理将在 promoteMemoryToRegisters 结束后进行
}
}
// 清理所有 Phi 的列表和映射
// 遍历 allPhiInstructions删除那些在 simplifyphi 后可能仍然存在的、但已经没有 uses 的 Phi
std::vector<PhiInst*> remainingPhis;
for(PhiInst* phi : allPhiInstructions) {
if(phi->getParent() && phi->getUses().empty()){ // 如果还在IR中但没有用处
// phi->getParent()->delete_inst(phi);
// 找到phi节点对应的迭代器
auto tofind = std::find_if(phi->getParent()->getInstructions().begin(), phi->getParent()->getInstructions().end(),
[phi](const auto &instr) { return instr.get() == phi; });
SysYIROptUtils::usedelete(phi); // 使用 SysYIROptUtils 删除指令
phi->getParent()->getInstructions().erase(tofind);
changed = true;
} else if (phi->getParent()) { // 仍在IR中且有uses
remainingPhis.push_back(phi);
}
}
allPhiInstructions = remainingPhis; // 更新为仅包含未被删除的 Phi
// 重新清理 phiMap 中已经删除的 Phi 指令项
for (auto& pairBBPhiMap : phiMap) {
std::vector<PhiInst*> phisToRemoveFromMap;
for (auto& pairPhiAlloca : pairBBPhiMap.second) {
if (!pairPhiAlloca.first->getParent()) { // 如果 Phi 已经被删除
phisToRemoveFromMap.push_back(pairPhiAlloca.first);
}
}
for (PhiInst* phi : phisToRemoveFromMap) {
pairBBPhiMap.second.erase(phi);
}
}
return changed;
}
// --- run函数实现 ---
void Mem2Reg::run() {
// 每次运行整个 Mem2Reg Pass 时,重新进行分析
controlFlowAnalysis->clear();
controlFlowAnalysis->runControlFlowAnalysis();
activeVarAnalysis->clear();
// 假设 dataFlowAnalysisUtils 可以管理和运行各个分析器
dataFlowAnalysisUtils.addBackwardAnalyzer(activeVarAnalysis);
dataFlowAnalysisUtils.backwardAnalyze(pModule); // 运行活跃变量分析
bool globalChanged = false;
// 循环直到没有更多的 alloca 可以被提升
// 每次 promoteMemoryToRegisters 会尝试在一个函数内完成所有 Mem2Reg 优化
do {
globalChanged = false;
for (const auto& [_, func] : pModule->getFunctions()) {
// 对每个函数执行 Mem2Reg
if (promoteMemoryToRegisters(func.get())) {
globalChanged = true;
// 如果一个函数发生改变,可能影响其他函数或需要重新分析
// 因此需要重新运行控制流和活跃变量分析,以备下一次循环
controlFlowAnalysis->clear();
controlFlowAnalysis->runControlFlowAnalysis();
activeVarAnalysis->clear();
dataFlowAnalysisUtils.backwardAnalyze(pModule); // 重新分析活跃变量
}
}
} while (globalChanged); // 如果全局有任何函数发生改变,则继续迭代
// 最终清理和重新分析
controlFlowAnalysis->clear();
controlFlowAnalysis->runControlFlowAnalysis();
activeVarAnalysis->clear();
dataFlowAnalysisUtils.backwardAnalyze(pModule);
}
} // namespace sysy

132
src/Pass.cpp Normal file
View File

@@ -0,0 +1,132 @@
// Pass.cpp
#include "Pass.h"
#include "SysYIRCFGOpt.h"
#include "SysYIRPrinter.h"
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <vector>
#include "Dom.h"
#include "Liveness.h"
namespace sysy {
extern int DEBUG; // 全局调试标志
// ======================================================================
// 封装优化流程的函数包含Pass注册和迭代运行逻辑
// ======================================================================
void PassManager::runOptimizationPipeline(Module* moduleIR, int optLevel) {
if (DEBUG) std::cout << "--- Starting Middle-End Optimizations (Level -O" << optLevel << ") ---\n";
// 1. 注册所有可用的分析遍和优化遍
// 这些注册只需执行一次。
sysy::registerAnalysisPass<sysy::DominatorTreeAnalysisPass>();
sysy::registerAnalysisPass<sysy::LivenessAnalysisPass>();
// 2. 创建遍管理器
sysy::PassManager pm(moduleIR);
// 3. 根据优化级别添加不同的优化遍
if (optLevel >= 1) {
if (DEBUG) std::cout << "Applying -O1 optimizations.\n";
// 4. 循环执行遍,直到 IR 稳定 (不再有任何遍修改 IR)
bool changed_in_iteration = true;
int iteration_count = 0;
while(changed_in_iteration) {
iteration_count++;
if (DEBUG) std::cout << "Optimization iteration: " << iteration_count << std::endl;
changed_in_iteration = pm.run(); // 运行一次所有添加到 PassManager 的遍
if (DEBUG && changed_in_iteration) {
std::cout << "=== IR after iteration " << iteration_count << " ===\n";
SysYPrinter printer_iter(moduleIR);
printer_iter.printIR();
}
}
if (DEBUG) std::cout << "Optimizations stabilized after " << iteration_count << " iterations.\n";
}
if (DEBUG) {
std::cout << "=== Final IR After Middle-End Optimizations (Level -O" << optLevel << ") ===\n";
SysYPrinter printer(moduleIR);
printer.printIR();
}
}
void PassManager::addPass(void *passID) {
PassRegistry &registry = PassRegistry::getPassRegistry();
std::unique_ptr<Pass> P = registry.createPass(passID);
if (!P) {
// Error: Pass not found or failed to create
return;
}
passes.push_back(std::move(P));
}
// 运行所有注册的遍
bool PassManager::run() {
bool changed = false;
for (const auto &p : passes) {
bool passChanged = false; // 记录当前遍是否修改了 IR
// 处理优化遍的分析依赖和失效
if (p->getPassKind() == Pass::PassKind::Optimization) {
OptimizationPass *optPass = static_cast<OptimizationPass *>(p.get());
std::set<void *> analysisDependencies;
std::set<void *> analysisInvalidations;
optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations);
// PassManager 不显式运行分析依赖。
// 而是优化遍在 runOnFunction 内部通过 AnalysisManager.getAnalysisResult 按需请求。
}
if (p->getGranularity() == Pass::Granularity::Module) {
passChanged = p->runOnModule(pmodule, analysisManager);
} else if (p->getGranularity() == Pass::Granularity::Function) {
for (auto &funcPair : pmodule->getFunctions()) {
Function *F = funcPair.second.get();
passChanged = p->runOnFunction(F, analysisManager) || passChanged;
if (passChanged && p->getPassKind() == Pass::PassKind::Optimization) {
OptimizationPass *optPass = static_cast<OptimizationPass *>(p.get());
std::set<void *> analysisDependencies;
std::set<void *> analysisInvalidations;
optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations);
for (void *invalidationID : analysisInvalidations) {
analysisManager.invalidateAnalysis(invalidationID, F);
}
}
}
} else if (p->getGranularity() == Pass::Granularity::BasicBlock) {
for (auto &funcPair : pmodule->getFunctions()) {
Function *F = funcPair.second.get();
for (auto &bbPtr : funcPair.second->getBasicBlocks()) {
passChanged = p->runOnBasicBlock(bbPtr.get(), analysisManager) || passChanged;
if (passChanged && p->getPassKind() == Pass::PassKind::Optimization) {
OptimizationPass *optPass = static_cast<OptimizationPass *>(p.get());
std::set<void *> analysisDependencies;
std::set<void *> analysisInvalidations;
optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations);
for (void *invalidationID : analysisInvalidations) {
analysisManager.invalidateAnalysis(invalidationID, F);
}
}
}
}
}
changed = changed || passChanged;
}
return changed;
}
} // namespace sysy

View File

@@ -1,122 +0,0 @@
#include "Reg2Mem.h"
#include <cstddef>
#include <iostream>
#include <list>
#include <memory>
namespace sysy {
/**
* 删除phi节点
* 删除phi节点后可能会生成冗余存储代码
*/
void Reg2Mem::DeletePhiInst(){
auto &functions = pModule->getFunctions();
for (auto &function : functions) {
auto basicBlocks = function.second->getBasicBlocks();
for (auto &basicBlock : basicBlocks) {
for (auto iter = basicBlock->begin(); iter != basicBlock->end();) {
auto &instruction = *iter;
if (instruction->isPhi()) {
auto predBlocks = basicBlock->getPredecessors();
// 寻找源和目的
// 目的就是phi指令的第一个操作数
// 源就是phi指令的后续操作数
auto destination = instruction->getOperand(0);
int predBlockindex = 0;
for (auto &predBlock : predBlocks) {
++predBlockindex;
// 判断前驱块儿只有一个后继还是多个后继
// 如果有多个
auto source = instruction->getOperand(predBlockindex);
if (source == destination) {
continue;
}
// std::cout << predBlock->getNumSuccessors() << std::endl;
if (predBlock->getNumSuccessors() > 1) {
// 创建一个basicblock
auto newbasicBlock = function.second->addBasicBlock();
std::stringstream ss;
ss << "phidel.L" << pBuilder->getLabelIndex();
newbasicBlock->setName(ss.str());
ss.str("");
// // 修改前驱后继关系
basicBlock->replacePredecessor(predBlock, newbasicBlock);
// predBlock = newbasicBlock;
newbasicBlock->addPredecessor(predBlock);
newbasicBlock->addSuccessor(basicBlock.get());
predBlock->removeSuccessor(basicBlock.get());
predBlock->addSuccessor(newbasicBlock);
// std::cout << "the block name is " << basicBlock->getName() << std::endl;
// for (auto pb : basicBlock->getPredecessors()) {
// // newbasicBlock->addPredecessor(pb);
// std::cout << pb->getName() << std::endl;
// }
// sysy::BasicBlock::conectBlocks(newbasicBlock, static_cast<BasicBlock *>(basicBlock.get()));
// 若后为跳转指令,应该修改跳转指令所到达的位置
auto thelastinst = predBlock->end();
(--thelastinst);
if (thelastinst->get()->isConditional() || thelastinst->get()->isUnconditional()) { // 如果是跳转指令
auto opnum = thelastinst->get()->getNumOperands();
for (size_t i = 0; i < opnum; i++) {
if (thelastinst->get()->getOperand(i) == basicBlock.get()) {
thelastinst->get()->replaceOperand(i, newbasicBlock);
}
}
}
// 在新块中插入store指令
pBuilder->setPosition(newbasicBlock, newbasicBlock->end());
// pBuilder->createStoreInst(source, destination);
if (source->isInt() || source->isFloat()) {
pBuilder->createStoreInst(source, destination);
} else {
auto loadInst = pBuilder->createLoadInst(source);
pBuilder->createStoreInst(loadInst, destination);
}
// pBuilder->createMoveInst(Instruction::kMove, destination->getType(), destination, source,
// newbasicBlock);
pBuilder->setPosition(newbasicBlock, newbasicBlock->end());
pBuilder->createUncondBrInst(basicBlock.get(), {});
} else {
// 如果前驱块只有一个后继
auto thelastinst = predBlock->end();
(--thelastinst);
// std::cout << predBlock->getName() << std::endl;
// std::cout << thelastinst->get() << std::endl;
// std::cout << "First point 11 " << std::endl;
if (thelastinst->get()->isConditional() || thelastinst->get()->isUnconditional()) {
// 在跳转语句前insert st指令
pBuilder->setPosition(predBlock, thelastinst);
} else {
pBuilder->setPosition(predBlock, predBlock->end());
}
if (source->isInt() || source->isFloat()) {
pBuilder->createStoreInst(source, destination);
} else {
auto loadInst = pBuilder->createLoadInst(source);
pBuilder->createStoreInst(loadInst, destination);
}
}
}
// 删除phi指令
auto &instructions = basicBlock->getInstructions();
SysYIROptUtils::usedelete(iter->get());
iter = instructions.erase(iter);
if (basicBlock->getNumInstructions() == 0) {
if (basicBlock->getNumSuccessors() == 1) {
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
}
}
} else {
break;
}
}
}
}
}
} // namespace sysy

View File

@@ -1,36 +0,0 @@
#pragma once
#include "IR.h"
#include "SysYIRAnalyser.h"
#include "SysYIRPrinter.h"
#include "SysYIROptUtils.h"
namespace sysy {
class DeadCodeElimination {
private:
Module *pModule;
ControlFlowAnalysis *pCFA; // 控制流分析指针
ActiveVarAnalysis *pAVA; // 活跃变量分析指针
DataFlowAnalysisUtils dataFlowAnalysisUtils; // 数据流分析工具类
public:
explicit DeadCodeElimination(Module *pMoudle,
ControlFlowAnalysis *pCFA = nullptr,
ActiveVarAnalysis *pAVA = nullptr)
: pModule(pMoudle), pCFA(pCFA), pAVA(pAVA), dataFlowAnalysisUtils() {} // 构造函数
// TODO根据参数传入的passes来运行不同的死代码删除流程
// void runDCEPipeline(const std::vector<std::string>& passes = {
// "dead-store", "redundant-load-store", "dead-load", "dead-alloca", "dead-global"
// });
void runDCEPipeline(); // 运行死代码删除
void eliminateDeadStores(Function* func, bool& changed); // 消除无用存储
void eliminateDeadLoads(Function* func, bool& changed); // 消除无用加载
void eliminateDeadAllocas(Function* func, bool& changed); // 消除无用内存分配
void eliminateDeadGlobals(bool& changed); // 消除无用全局变量
void eliminateDeadIndirectiveAllocas(Function* func, bool& changed); // 消除无用间接内存分配(phi节点)
void eliminateDeadRedundantLoadStore(Function* func, bool& changed); // 消除冗余加载和存储
};
} // namespace sysy

View File

@@ -41,7 +41,7 @@ public:
// 实现 getPassID
void* getPassID() const override { return &ID; }
bool runOnFunction(Function* F) override;
bool runOnFunction(Function* F, AnalysisManager &AM) override;
std::unique_ptr<AnalysisResultBase> getResult() override;

View File

@@ -20,7 +20,8 @@ class Instruction;
class LivenessAnalysisResult : public AnalysisResultBase {
public:
LivenessAnalysisResult(Function *F); // 构造函数,需要一个函数来关联结果
LivenessAnalysisResult::LivenessAnalysisResult(Function *F) : AssociatedFunction(F) {}
// 获取给定基本块的 LiveIn 集合
const std::set<Value *> *getLiveIn(BasicBlock *BB) const;
@@ -52,7 +53,7 @@ public:
static char ID; // LLVM 风格的唯一 ID
LivenessAnalysisPass() : AnalysisPass("LivenessAnalysis", Pass::Granularity::Function) {}
// 实现 getPassID
void *getPassID() const override { return &ID; }

View File

@@ -1,79 +0,0 @@
// 假设 Mem2Reg.h 看起来像这样 (你需要根据实际情况调整)
#ifndef SYSY_MEM2REG_H
#define SYSY_MEM2REG_H
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <queue> // For computeIteratedDomFrontiers
// Include your IR and analysis headers
#include "IR.h"
#include "IRBuilder.h"
#include "SysYIRAnalyser.h"
#include "SysYIROptUtils.h"
namespace sysy {
class Mem2Reg {
private:
Module* pModule;
IRBuilder* pBuilder;
ControlFlowAnalysis* controlFlowAnalysis;
ActiveVarAnalysis* activeVarAnalysis;
DataFlowAnalysisUtils dataFlowAnalysisUtils; // If this is part of Mem2Reg or an external helper
public:
Mem2Reg(Module* module, IRBuilder* builder, ControlFlowAnalysis* cfa, ActiveVarAnalysis* ava)
: pModule(module), pBuilder(builder), controlFlowAnalysis(cfa), activeVarAnalysis(ava) {}
// Constructor initializes members
void run();
// --- 新增的私有成员变量和方法用于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;
// BasicBlock -> Map of (PhiInst, Original AllocaInst)
// 用于在 rename 阶段通过 phi 指令找到它代表的原始 alloca
std::unordered_map<BasicBlock*, std::unordered_map<PhiInst*, AllocaInst*>> phiMap;
std::vector<PhiInst*> allPhiInstructions; // 收集所有创建的 Phi 指令以便后续简化和清理
// --- 核心 SSA 转换辅助函数 ---
// 计算给定定义块集合的迭代支配边界
std::unordered_set<BasicBlock*> computeIteratedDomFrontiers(const std::unordered_set<BasicBlock*>& blocks);
// 分析一个 alloca 的所有 uses填充 allocaDefsBlock 和 allocaUsesBlock
void allocaAnalysis(AllocaInst* alloca);
// 判断一个 alloca 是否可以被提升为寄存器 (无地址逃逸,标量类型)
bool is_promoted(AllocaInst* alloca);
// 在迭代支配边界处插入 Phi 指令
void insertPhiNodes(Function* func);
// 递归地重命名基本块中的变量并填充 Phi 指令
// 这里的 `count` 和 `stacks` 是临时的,用于 DFS 过程中传递状态
void renameBlock(BasicBlock* block,
std::unordered_map<AllocaInst*, Value*>& currentIncomings,
std::unordered_set<BasicBlock*>& visitedBlocks); // 修改为传递 map 和 set
// 简化冗余的 Phi 指令 (当所有输入都相同时)
void simplifyphi(PhiInst* phi);
// 获取前驱块在后继块前驱列表中的索引,用于 Phi 指令入边
int getPredIndex(BasicBlock* pred, BasicBlock* succ);
// --- Mem2Reg 的主要工作流函数 ---
// 对单个函数执行内存到寄存器的提升
bool promoteMemoryToRegisters(Function* func);
};
} // namespace sysy
#endif // SYSY_MEM2REG_H

View File

@@ -111,6 +111,9 @@ private:
// AnalysisManager: 负责管理和提供分析结果
// ======================================================================
class AnalysisManager {
private:
std::map<std::pair<Function *, void *>, std::unique_ptr<AnalysisResultBase>> cachedResults;
// cachedResults 存储分析结果,键是 (Function*, AnalysisPass ID)
public:
AnalysisManager() = default;
~AnalysisManager() = default;
@@ -172,97 +175,38 @@ public:
cachedResults = std::move(newCachedResults);
}
}
private:
std::map<std::pair<Function *, void *>, std::unique_ptr<AnalysisResultBase>> cachedResults;
};
// ======================================================================
// PassManager遍管理器
// ======================================================================
class PassManager {
private:
std::vector<std::unique_ptr<Pass>> passes;
AnalysisManager analysisManager;
Module *pmodule;
AnalysisManager &AM; // 引用 AnalysisManager用于获取分析结果
public:
PassManager() = default;
~PassManager() = default;
// 添加遍:现在接受 Pass 的 ID而不是直接的 unique_ptr
void addPass(void *passID) {
PassRegistry &registry = PassRegistry::getPassRegistry();
std::unique_ptr<Pass> P = registry.createPass(passID);
if (!P) {
// Error: Pass not found or failed to create
return;
}
passes.push_back(std::move(P));
PassManager(Module *module) : pmodule(module) {
analysisManager = AnalysisManager(); // 初始化分析管理器
}
// 运行所有注册的遍
bool run(Module *M) {
bool changed = false;
for (const auto &p : passes) {
bool passChanged = false; // 记录当前遍是否修改了 IR
bool run();
// 运行优化管道主要负责注册和运行优化遍
// 这里可以根据 optLevel 和 DEBUG 控制不同的优化遍
void runOptimizationPipeline(Module* moduleIR, int optLevel);
// 处理优化遍的分析依赖和失效
if (p->getPassKind() == Pass::PassKind::Optimization) {
OptimizationPass *optPass = static_cast<OptimizationPass *>(p.get());
std::set<void *> analysisDependencies;
std::set<void *> analysisInvalidations;
optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations);
// PassManager 不显式运行分析依赖。
// 而是优化遍在 runOnFunction 内部通过 AnalysisManager.getAnalysisResult 按需请求。
}
if (p->getGranularity() == Pass::Granularity::Module) {
passChanged = p->runOnModule(M, AM);
} else if (p->getGranularity() == Pass::Granularity::Function) {
for (auto &funcPair : M->getFunctions()) {
Function *F = funcPair.second.get();
passChanged = p->runOnFunction(F, AM) || passChanged;
if (passChanged && p->getPassKind() == Pass::PassKind::Optimization) {
OptimizationPass *optPass = static_cast<OptimizationPass *>(p.get());
std::set<void *> analysisDependencies;
std::set<void *> analysisInvalidations;
optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations);
for (void *invalidationID : analysisInvalidations) {
analysisManager.invalidateAnalysis(invalidationID, F);
}
}
}
} else if (p->getGranularity() == Pass::Granularity::BasicBlock) {
for (auto &funcPair : M->getFunctions()) {
Function *F = funcPair.second.get();
for (auto &bbPtr : funcPair.second->getBasicBlocks()) {
passChanged = p->runOnBasicBlock(bbPtr.get(), AM) || passChanged;
if (passChanged && p->getPassKind() == Pass::PassKind::Optimization) {
OptimizationPass *optPass = static_cast<OptimizationPass *>(p.get());
std::set<void *> analysisDependencies;
std::set<void *> analysisInvalidations;
optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations);
for (void *invalidationID : analysisInvalidations) {
analysisManager.invalidateAnalysis(invalidationID, F);
}
}
}
}
}
changed = changed || passChanged;
}
return changed;
}
// 添加遍:现在接受 Pass 的 ID而不是直接的 unique_ptr
void addPass(void *passID);
AnalysisManager &getAnalysisManager() { return analysisManager; }
private:
std::vector<std::unique_ptr<Pass>> passes;
AnalysisManager analysisManager;
};
// ======================================================================

View File

@@ -1,22 +0,0 @@
#pragma once
#include "IR.h"
#include "IRBuilder.h"
#include "SysYIROptUtils.h"
namespace sysy {
/**
* Reg2Mem(后端未做phi指令翻译)
*/
class Reg2Mem {
private:
Module *pModule;
IRBuilder *pBuilder;
public:
Reg2Mem(Module *pMoudle, IRBuilder *pBuilder) : pModule(pMoudle), pBuilder(pBuilder) {}
void DeletePhiInst();
};
} // namespace sysy

View File

@@ -1,59 +0,0 @@
#pragma once
#include "IR.h"
namespace sysy {
// 前置声明
class FunctionPass;
class ModulePass;
class AnalysisPass;
class PassManager;
// 抽象基类 Pass
class Pass {
public:
enum PassKind {
PK_Function,
PK_Module,
PK_Analysis
};
Pass(PassKind kind, const std::string& name) : Kind(kind), Name(name) {}
virtual ~Pass() = default;
PassKind getPassKind() const { return Kind; }
const std::string& getPassName() const { return Name; }
// 每个Pass需要实现此方法来执行其逻辑
// 具体的run方法将根据Pass类型在FunctionPass和ModulePass中定义
protected:
PassKind Kind;
std::string Name;
};
// 针对函数的优化遍
class FunctionPass : public Pass {
public:
FunctionPass(const std::string& name) : Pass(PK_Function, name) {}
// 真正的优化逻辑将在此方法中实现
virtual bool runOnFunction(Function& F) = 0;
};
// 针对模块的优化遍
class ModulePass : public Pass {
public:
ModulePass(const std::string& name) : Pass(PK_Module, name) {}
// 真正的优化逻辑将在此方法中实现
virtual bool runOnModule(Module& M) = 0;
};
// 分析遍
class AnalysisPass : public Pass {
public:
AnalysisPass(const std::string& name) : Pass(PK_Analysis, name) {}
// 分析遍通常需要一个模块或函数作为输入,并计算出分析结果
// 具体分析结果的存储和访问方式需要设计
};
} // namespace sysy

View File

@@ -13,13 +13,10 @@ using namespace antlr4;
#include "SysYIRGenerator.h"
#include "SysYIRPrinter.h"
#include "SysYIRCFGOpt.h"
#include "SysYIRCFGOpt.h" // 包含 CFG 优化
#include "RISCv64Backend.h"
// #include "SysYIRAnalyser.h"
// #include "DeadCodeElimination.h"
#include "Pass.h" // 包含新的 Pass 框架
#include "AddressCalculationExpansion.h"
// #include "Mem2Reg.h"
// #include "Reg2Mem.h"
using namespace sysy;
@@ -131,17 +128,13 @@ int main(int argc, char **argv) {
if (argStopAfter == "ird") {
DEBUG = 1; // 这里可能需要更精细地控制 DEBUG 的开启时机和范围
}
// 默认优化 pass (在所有优化级别都会执行)
SysYCFGOpt cfgopt(moduleIR, builder);
cfgopt.SysYOptimizateAfterIR();
// ControlFlowAnalysis cfa(moduleIR);
// cfa.init();
// ActiveVarAnalysis ava;
// ava.init(moduleIR);
// 创建 Pass 管理器并运行优化管道
PassManager passManager(moduleIR); // 创建 Pass 管理器
passManager.runOptimizationPipeline(moduleIR, optLevel);
if (DEBUG) {
cout << "=== After CFA & AVA (Default) ===\n";
cout << "=== Init IR ===\n";
SysYPrinter(moduleIR).printIR(); // 临时打印器用于调试
}
AddressCalculationExpansion ace(moduleIR, builder);