[midend]优化中端框架,移除无用旧代码,ignore格式文件
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -54,3 +54,4 @@ __init__.py
|
||||
.DS_*
|
||||
|
||||
antlr/
|
||||
.clang-format
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
515
src/Mem2Reg.cpp
515
src/Mem2Reg.cpp
@@ -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
132
src/Pass.cpp
Normal 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 ®istry = 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
|
||||
122
src/Reg2Mem.cpp
122
src/Reg2Mem.cpp
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ 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;
|
||||
|
||||
@@ -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
|
||||
@@ -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 ®istry = 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();
|
||||
|
||||
// 处理优化遍的分析依赖和失效
|
||||
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);
|
||||
// 运行优化管道主要负责注册和运行优化遍
|
||||
// 这里可以根据 optLevel 和 DEBUG 控制不同的优化遍
|
||||
void runOptimizationPipeline(Module* moduleIR, int optLevel);
|
||||
|
||||
// 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;
|
||||
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user