Merge branch 'DCE' into backend

This commit is contained in:
Lixuanwang
2025-06-25 16:04:42 +08:00
13 changed files with 2347 additions and 5 deletions

View File

@@ -18,6 +18,10 @@ add_executable(sysyc
# Backend.cpp
SysYIRPrinter.cpp
SysYIROptPre.cpp
SysYIRAnalyser.cpp
DeadCodeElimination.cpp
Mem2Reg.cpp
Reg2Mem.cpp
RISCv64Backend.cpp
)
target_include_directories(sysyc PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include)

249
src/DeadCodeElimination.cpp Normal file
View File

@@ -0,0 +1,249 @@
#include "DeadCodeElimination.h"
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 (isGlobal(pointer) || (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;
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;
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;
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;
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;
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;
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;
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);
usedelete(loadInst);
iter = instrs.erase(iter);
// 删除 prevStore 这里是不是可以留给删除无用store处理
// if (prevStore->getUses().empty()) {
// usedelete(prevStore);
// instrs.erase(prevIter); // 删除 prevStore
// }
continue; // 跳过 ++iter因为已经移动迭代器
}
}
}
}
}
}
}
}
++iter;
}
}
}
bool DeadCodeElimination::isGlobal(Value *val){
auto gval = dynamic_cast<GlobalValue *>(val);
return gval != nullptr;
}
bool DeadCodeElimination::isArr(Value *val){
auto aval = dynamic_cast<AllocaInst *>(val);
return aval != nullptr && aval->getNumDims() != 0;
}
void DeadCodeElimination::usedelete(Instruction *instr){
for (auto &use1 : instr->getOperands()) {
auto val1 = use1->getValue();
val1->removeUse(use1);
}
}
} // namespace sysy

View File

@@ -0,0 +1,822 @@
#include "Mem2Reg.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <memory>
#include <queue>
#include <stack>
#include <string>
#include <unordered_map>
#include <utility>
#include "IR.h"
#include "SysYIRAnalyser.h"
#include "SysYIRPrinter.h"
namespace sysy {
// 计算给定变量的定义块集合的迭代支配边界
// TODO优化Semi-Naive IDF
std::unordered_set<BasicBlock *> Mem2Reg::computeIterDf(const std::unordered_set<BasicBlock *> &blocks) {
std::unordered_set<BasicBlock *> workList;
std::unordered_set<BasicBlock *> ret_list;
workList.insert(blocks.begin(), blocks.end());
while (!workList.empty()) {
auto n = workList.begin();
BlockAnalysisInfo* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(*n);
auto DFs = blockInfo->getDomFrontiers();
for (auto c : DFs) {
// 如果c不在ret_list中则将其加入ret_list和workList
// 这里的c是n的支配边界
// 也就是n的支配边界中的块
// 需要注意的是,支配边界是一个集合,所以可能会有重复
if (ret_list.count(c) == 0U) {
ret_list.emplace(c);
workList.emplace(c);
}
}
workList.erase(n);
}
return ret_list;
}
/**
* 计算value2Blocks的映射包括value2AllocBlocks、value2DefBlocks以及value2UseBlocks
* 其中value2DefBlocks可用于计算迭代支配边界来插入相应变量的phi结点
* 这里的value2AllocBlocks、value2DefBlocks和value2UseBlocks改变了函数级别的分析信息
*/
auto Mem2Reg::computeValue2Blocks() -> void {
SysYPrinter printer(pModule); // 初始化打印机
std::cout << "===== Start computeValue2Blocks =====" << std::endl;
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
std::cout << "\nProcessing function: " << func->getName() << std::endl;
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
if (!funcInfo) {
std::cerr << "ERROR: No analysis info for function " << func->getName() << std::endl;
continue;
}
auto basicBlocks = func->getBasicBlocks();
std::cout << "BasicBlocks count: " << basicBlocks.size() << std::endl;
for (auto &it : basicBlocks) {
auto basicBlock = it.get();
std::cout << "\nProcessing BB: " << basicBlock->getName() << std::endl;
// printer.printBlock(basicBlock); // 打印基本块内容
auto &instrs = basicBlock->getInstructions();
for (auto &instr : instrs) {
std::cout << " Analyzing instruction: ";
printer.printInst(instr.get());
std::cout << std::endl;
if (instr->isAlloca()) {
if (!(isArr(instr.get()) || isGlobal(instr.get()))) {
std::cout << " Found alloca: ";
printer.printInst(instr.get());
std::cout << " -> Adding to allocBlocks" << std::endl;
funcInfo->addValue2AllocBlocks(instr.get(), basicBlock);
} else {
std::cout << " Skip array/global alloca: ";
printer.printInst(instr.get());
std::cout << std::endl;
}
}
else if (instr->isStore()) {
auto val = instr->getOperand(1);
std::cout << " Store target: ";
printer.printInst(dynamic_cast<Instruction *>(val));
if (!(isArr(val) || isGlobal(val))) {
std::cout << " Adding store to defBlocks for value: ";
printer.printInst(dynamic_cast<Instruction *>(instr.get()));
std::cout << std::endl;
// 将store的目标值添加到defBlocks中
funcInfo->addValue2DefBlocks(val, basicBlock);
} else {
std::cout << " Skip array/global store" << std::endl;
}
}
else if (instr->isLoad()) {
auto val = instr->getOperand(0);
std::cout << " Load source: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << std::endl;
if (!(isArr(val) || isGlobal(val))) {
std::cout << " Adding load to useBlocks for value: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << std::endl;
funcInfo->addValue2UseBlocks(val, basicBlock);
} else {
std::cout << " Skip array/global load" << std::endl;
}
}
}
}
// 打印分析结果
std::cout << "\nAnalysis results for function " << func->getName() << ":" << std::endl;
auto &allocMap = funcInfo->getValue2AllocBlocks();
std::cout << "AllocBlocks (" << allocMap.size() << "):" << std::endl;
for (auto &[val, bb] : allocMap) {
std::cout << " ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << " in BB: " << bb->getName() << std::endl;
}
auto &defMap = funcInfo->getValue2DefBlocks();
std::cout << "DefBlocks (" << defMap.size() << "):" << std::endl;
for (auto &[val, bbs] : defMap) {
std::cout << " ";
printer.printInst(dynamic_cast<Instruction *>(val));
for (const auto &[bb, count] : bbs) {
std::cout << " in BB: " << bb->getName() << " (count: " << count << ")";
}
}
auto &useMap = funcInfo->getValue2UseBlocks();
std::cout << "UseBlocks (" << useMap.size() << "):" << std::endl;
for (auto &[val, bbs] : useMap) {
std::cout << " ";
printer.printInst(dynamic_cast<Instruction *>(val));
for (const auto &[bb, count] : bbs) {
std::cout << " in BB: " << bb->getName() << " (count: " << count << ")";
}
}
}
std::cout << "===== End computeValue2Blocks =====" << std::endl;
}
/**
* @brief 级联关系的顺带消除用于llvm mem2reg类预优化1
*
* 采用队列进行模拟从某种程度上来看其实可以看作是UD链的反向操作
*
* @param [in] instr store指令使用的指令
* @param [in] changed 不动点法的判断标准,地址传递
* @param [in] func 指令所在函数
* @param [in] block 指令所在基本块
* @param [in] instrs 基本块所在指令集合,地址传递
* @return 无返回值,但满足条件的情况下会对指令进行删除
*/
auto Mem2Reg::cascade(Instruction *instr, bool &changed, Function *func, BasicBlock *block,
std::list<std::unique_ptr<Instruction>> &instrs) -> void {
if (instr != nullptr) {
if (instr->isUnary() || instr->isBinary() || instr->isLoad()) {
std::queue<Instruction *> toRemove;
toRemove.push(instr);
while (!toRemove.empty()) {
auto top = toRemove.front();
toRemove.pop();
auto operands = top->getOperands();
for (const auto &operand : operands) {
auto elem = dynamic_cast<Instruction *>(operand->getValue());
if (elem != nullptr) {
if ((elem->isUnary() || elem->isBinary() || elem->isLoad()) && elem->getUses().size() == 1 &&
elem->getUses().front()->getUser() == top) {
toRemove.push(elem);
} else if (elem->isAlloca()) {
// value2UseBlock中该block对应次数-1如果该变量的该useblock中count减为0了则意味着
// 该block其他地方也没用到该alloc了故从value2UseBlock中删除
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
auto res = funcInfo->removeValue2UseBlock(elem, block);
// 只要有一次返回了true就说明有变化
if (res) {
changed = true;
}
}
}
}
auto tofind =
std::find_if(instrs.begin(), instrs.end(), [&top](const auto &instr) { return instr.get() == top; });
assert(tofind != instrs.end());
usedelete(tofind->get());
instrs.erase(tofind);
}
}
}
}
/**
* @brief llvm mem2reg预优化1: 删除不含load的alloc和store
*
* 1. 删除不含load的alloc和store
* 2. 删除store指令之前的用于作store指令第0个操作数的那些级联指令就冗余了也要删除
* 3. 删除之后可能有些变量的load使用恰好又没有了因此再次从第一步开始循环这里使用不动点法
*
* @note 额外说明:由于删除了级联关系,所以这里的方法有点儿激进;
* 同时也考虑了级联关系时如果调用了函数可能会有side effect所以没有删除调用函数的级联关系
* 而且关于函数参数的alloca不会在指令中删除也不会在value2Alloca中删除;
* 同样地我们不考虑数组和global不过这里的代码是基于value2blocks的在value2blocks中已经考虑了所以不用显式指明
*
* @param [in] void
* @return 无返回值,但满足条件的情况下会对指令进行删除
*/
auto Mem2Reg::preOptimize1() -> void {
SysYPrinter printer(pModule); // 初始化打印机
auto &functions = pModule->getFunctions();
std::cout << "===== Start preOptimize1 =====" << std::endl;
for (const auto &function : functions) {
auto func = function.second.get();
std::cout << "\nProcessing function: " << func->getName() << std::endl;
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
if (!funcInfo) {
std::cerr << "ERROR: No analysis info for function " << func->getName() << std::endl;
continue;
}
auto &vToDefB = funcInfo->getValue2DefBlocks();
auto &vToUseB = funcInfo->getValue2UseBlocks();
auto &vToAllocB = funcInfo->getValue2AllocBlocks();
// 打印初始状态
std::cout << "Initial allocas: " << vToAllocB.size() << std::endl;
for (auto &[val, bb] : vToAllocB) {
std::cout << " Alloca: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << " in BB: " << bb->getName() << std::endl;
}
// 阶段1删除无store的alloca
std::cout << "\nPhase 1: Remove unused allocas" << std::endl;
for (auto iter = vToAllocB.begin(); iter != vToAllocB.end();) {
auto val = iter->first;
auto bb = iter->second;
std::cout << "Checking alloca: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << " in BB: " << bb->getName() << std::endl;
// 如果该alloca没有对应的store指令且不在函数参数中
// 这里的vToDefB是value2DefBlocksvToUseB是value2UseBlocks
// 打印vToDefB
std::cout << "DefBlocks (" << vToDefB.size() << "):" << std::endl;
for (auto &[val, bbs] : vToDefB) {
std::cout << " ";
printer.printInst(dynamic_cast<Instruction *>(val));
for (const auto &[bb, count] : bbs) {
std::cout << " in BB: " << bb->getName() << " (count: " << count << ")" << std::endl;
}
}
std::cout << vToDefB.count(val) << std::endl;
bool hasStore = false;
if (vToDefB.count(val) == 0U &&
std::find(func->getEntryBlock()->getArguments().begin(),
func->getEntryBlock()->getArguments().end(),
val) == func->getEntryBlock()->getArguments().end()) {
std::cout << " Removing unused alloca: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << std::endl;
auto tofind = std::find_if(bb->getInstructions().begin(),
bb->getInstructions().end(),
[val](const auto &instr) {
return instr.get() == val;
});
if (tofind == bb->getInstructions().end()) {
std::cerr << "ERROR: Alloca not found in BB!" << std::endl;
++iter;
continue;
}
usedelete(tofind->get());
bb->getInstructions().erase(tofind);
iter = vToAllocB.erase(iter);
} else {
++iter;
}
}
// 阶段2删除无load的store
std::cout << "\nPhase 2: Remove dead stores" << std::endl;
bool changed = true;
int iteration = 0;
while (changed) {
changed = false;
iteration++;
std::cout << "\nIteration " << iteration << std::endl;
for (auto iter = vToDefB.begin(); iter != vToDefB.end();) {
auto val = iter->first;
std::cout << "Checking value: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << std::endl;
if (vToUseB.count(val) == 0U) {
std::cout << " Found dead store for value: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << std::endl;
auto blocks = funcInfo->getDefBlocksByValue(val);
for (auto block : blocks) {
std::cout << " Processing BB: " << block->getName() << std::endl;
// printer.printBlock(block); // 打印基本块内容
auto &instrs = block->getInstructions();
for (auto it = instrs.begin(); it != instrs.end();) {
if ((*it)->isStore() && (*it)->getOperand(1) == val) {
std::cout << " Removing store: ";
printer.printInst(it->get());
std::cout << std::endl;
auto valUsedByStore = dynamic_cast<Instruction *>((*it)->getOperand(0));
usedelete(it->get());
if (valUsedByStore != nullptr &&
valUsedByStore->getUses().size() == 1 &&
valUsedByStore->getUses().front()->getUser() == (*it).get()) {
std::cout << " Cascade deleting: ";
printer.printInst(valUsedByStore);
std::cout << std::endl;
cascade(valUsedByStore, changed, func, block, instrs);
}
it = instrs.erase(it);
changed = true;
} else {
++it;
}
}
}
// 删除对应的alloca
if (std::find(func->getEntryBlock()->getArguments().begin(),
func->getEntryBlock()->getArguments().end(),
val) == func->getEntryBlock()->getArguments().end()) {
auto bb = funcInfo->getAllocBlockByValue(val);
if (bb != nullptr) {
std::cout << " Removing alloca: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << " in BB: " << bb->getName() << std::endl;
funcInfo->removeValue2AllocBlock(val);
auto tofind = std::find_if(bb->getInstructions().begin(),
bb->getInstructions().end(),
[val](const auto &instr) {
return instr.get() == val;
});
if (tofind != bb->getInstructions().end()) {
usedelete(tofind->get());
bb->getInstructions().erase(tofind);
} else {
std::cerr << "ERROR: Alloca not found in BB!" << std::endl;
}
}
}
iter = vToDefB.erase(iter);
} else {
++iter;
}
}
}
}
std::cout << "===== End preOptimize1 =====" << std::endl;
}
/**
* @brief llvm mem2reg预优化2: 针对某个变量的Defblocks只有一个块的情况
*
* 1. 该基本块最后一次对该变量的store指令后的所有对该变量的load指令都可以替换为该基本块最后一次store指令的第0个操作数
* 2. 以该基本块为必经结点的结点集合中的对该变量的load指令都可以替换为该基本块最后一次对该变量的store指令的第0个操作数
* 3.
* 如果对该变量的所有load均替换掉了删除该基本块中最后一次store指令如果这个store指令是唯一的define那么再删除alloca指令不删除参数的alloca
* 4.
* 如果对该value的所有load都替换掉了对于该变量剩下还有store的话就转换成了preOptimize1的情况再调用preOptimize1进行删除
*
* @note 额外说明:同样有点儿激进;
* 同样不考虑数组和全局变量因为这些变量不会被mem2reg优化在value2blocks中已经考虑了所以不用显式指明
* 替换的操作采用了UD链进行简化和效率的提升
*
* @param [in] void
* @return 无返回值,但满足条件的情况下会对指令的操作数进行替换以及对指令进行删除
*/
auto Mem2Reg::preOptimize2() -> void {
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
auto values = funcInfo->getValuesOfDefBlock();
for (auto val : values) {
auto blocks = funcInfo->getDefBlocksByValue(val);
// 该val只有一个defining block
if (blocks.size() == 1) {
auto block = *blocks.begin();
auto &instrs = block->getInstructions();
auto rit = std::find_if(instrs.rbegin(), instrs.rend(),
[val](const auto &instr) { return instr->isStore() && instr->getOperand(1) == val; });
// 注意reverse_iterator求base后是指向下一个指令因此要减一才是原来的指令
assert(rit != instrs.rend());
auto it = --rit.base();
auto propogationVal = (*it)->getOperand(0);
// 其实该块中it后对该val的load指令也可以替换掉了
for (auto curit = std::next(it); curit != instrs.end();) {
if ((*curit)->isLoad() && (*curit)->getOperand(0) == val) {
curit->get()->replaceAllUsesWith(propogationVal);
usedelete(curit->get());
curit = instrs.erase(curit);
funcInfo->removeValue2UseBlock(val, block);
} else {
++curit;
}
}
// 在支配树后继结点中替换load指令的操作数
BlockAnalysisInfo* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(block);
std::vector<BasicBlock *> blkchildren;
// 获取该块的支配树后继结点
std::queue<BasicBlock *> q;
auto sdoms = blockInfo->getSdoms();
for (auto sdom : sdoms) {
q.push(sdom);
blkchildren.push_back(sdom);
}
while (!q.empty()) {
auto blk = q.front();
q.pop();
BlockAnalysisInfo* blkInfo = controlFlowAnalysis->getBlockAnalysisInfo(blk);
for (auto sdom : blkInfo->getSdoms()) {
q.push(sdom);
blkchildren.push_back(sdom);
}
}
for (auto child : blkchildren) {
auto &childInstrs = child->getInstructions();
for (auto childIter = childInstrs.begin(); childIter != childInstrs.end();) {
if ((*childIter)->isLoad() && (*childIter)->getOperand(0) == val) {
childIter->get()->replaceAllUsesWith(propogationVal);
usedelete(childIter->get());
childIter = childInstrs.erase(childIter);
funcInfo->removeValue2UseBlock(val, child);
} else {
++childIter;
}
}
}
// 如果对该val的所有load均替换掉了那么对于该val的defining block中的最后一个define也可以删除了
// 同时该块中前面对于该val的define也变成死代码了可调用preOptimize1进行删除
if (funcInfo->getUseBlocksByValue(val).empty()) {
usedelete(it->get());
instrs.erase(it);
auto change = funcInfo->removeValue2DefBlock(val, block);
if (change) {
// 如果define是唯一的且不是函数参数的alloca直接删alloca
if (std::find(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(),
val) == func->getEntryBlock()->getArguments().end()) {
auto bb = funcInfo->getAllocBlockByValue(val);
assert(bb != nullptr);
auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(),
[val](const auto &instr) { return instr.get() == val; });
usedelete(tofind->get());
bb->getInstructions().erase(tofind);
funcInfo->removeValue2AllocBlock(val);
}
} else {
// 如果该变量还有其他的define那么前面的define也变成死代码了
assert(!funcInfo->getDefBlocksByValue(val).empty());
assert(funcInfo->getUseBlocksByValue(val).empty());
preOptimize1();
}
}
}
}
}
}
/**
* @brief llvm mem2reg类预优化3针对某个变量的所有读写都在同一个块中的情况
*
* 1. 将每一个load替换成前一个store的值并删除该load
* 2. 如果在load前没有对该变量的store则不删除该load
* 3. 如果一个store后没有任何对改变量的load则删除该store
*
* @note 额外说明第二点不用显式处理因为我们的方法是从找到第一个store开始
* 第三点其实可以更激进一步地理解即每次替换了load之后它对应地那个store也可以删除了同时注意这里不要使用preoptimize1进行处理因为他们的级联关系是有用的即用来求load的替换值
* 同样地我们这里不考虑数组和全局变量因为这些变量不会被mem2reg优化不过这里在计算value2DefBlocks时已经跳过了所以不需要再显式处理了
* 替换的操作采用了UD链进行简化和效率的提升
*
* @param [in] void
* @return 无返回值,但满足条件的情况下会对指令的操作数进行替换以及对指令进行删除
*/
auto Mem2Reg::preOptimize3() -> void {
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
auto values = funcInfo->getValuesOfDefBlock();
for (auto val : values) {
auto sblocks = funcInfo->getDefBlocksByValue(val);
auto lblocks = funcInfo->getUseBlocksByValue(val);
if (sblocks.size() == 1 && lblocks.size() == 1 && *sblocks.begin() == *lblocks.begin()) {
auto block = *sblocks.begin();
auto &instrs = block->getInstructions();
auto it = std::find_if(instrs.begin(), instrs.end(),
[val](const auto &instr) { return instr->isStore() && instr->getOperand(1) == val; });
while (it != instrs.end()) {
auto propogationVal = (*it)->getOperand(0);
auto last = std::find_if(std::next(it), instrs.end(), [val](const auto &instr) {
return instr->isStore() && instr->getOperand(1) == val;
});
for (auto curit = std::next(it); curit != last;) {
if ((*curit)->isLoad() && (*curit)->getOperand(0) == val) {
curit->get()->replaceAllUsesWith(propogationVal);
usedelete(curit->get());
curit = instrs.erase(curit);
funcInfo->removeValue2UseBlock(val, block);
} else {
++curit;
}
}
// 替换了load之后它对应地那个store也可以删除了
if (!(std::find_if(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(),
[val](const auto &instr) { return instr == val; }) !=
func->getEntryBlock()->getArguments().end()) &&
last == instrs.end()) {
usedelete(it->get());
it = instrs.erase(it);
if (funcInfo->removeValue2DefBlock(val, block)) {
auto bb = funcInfo->getAllocBlockByValue(val);
if (bb != nullptr) {
auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(),
[val](const auto &instr) { return instr.get() == val; });
usedelete(tofind->get());
bb->getInstructions().erase(tofind);
funcInfo->removeValue2AllocBlock(val);
}
}
}
it = last;
}
}
}
}
}
/**
* @brief 为所有变量的定义块集合的迭代支配边界插入phi结点
*
* insertPhi是mem2reg的核心之一这里是对所有变量的迭代支配边界的phi结点插入无参数也无返回值
* 同样跳过对数组和全局变量的处理因为这些变量不会被mem2reg优化刚好这里在计算value2DefBlocks时已经跳过了所以不需要再显式处理了
* 同时我们进行了剪枝处理只有在基本块入口活跃的变量才插入phi函数
*
* @param [in] void
* @return 无返回值但是会在每个变量的迭代支配边界上插入phi结点
*/
auto Mem2Reg::insertPhi() -> void {
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
const auto &vToDefB = funcInfo->getValue2DefBlocks();
for (const auto &map_pair : vToDefB) {
// 首先为每个变量找到迭代支配边界
auto val = map_pair.first;
auto blocks = funcInfo->getDefBlocksByValue(val);
auto itDFs = computeIterDf(blocks);
// 然后在每个变量相应的迭代支配边界上插入phi结点
for (auto basicBlock : itDFs) {
const auto &actiTable = activeVarAnalysis->getActiveTable();
auto dval = dynamic_cast<User *>(val);
// 只有在基本块入口活跃的变量才插入phi函数
if (actiTable.at(basicBlock).front().count(dval) != 0U) {
pBuilder->createPhiInst(val->getType(), val, basicBlock);
}
}
}
}
}
/**
* @brief 重命名
*
* 重命名是mem2reg的核心之二这里是对单个块的重命名递归实现
* 同样跳过对数组和全局变量的处理因为这些变量不会被mem2reg优化
*
* @param [in] block 一个基本块
* @param [in] count 计数器,用于给变量重命名,地址传递
* @param [in] stacks 用于存储变量的栈,地址传递
* @return 无返回值
*/
auto Mem2Reg::rename(BasicBlock *block, std::unordered_map<Value *, int> &count,
std::unordered_map<Value *, std::stack<Instruction *>> &stacks) -> void {
auto &instrs = block->getInstructions();
std::unordered_map<Value *, int> valPop;
// 第一大步:对块中的所有指令遍历处理
for (auto iter = instrs.begin(); iter != instrs.end();) {
auto instr = iter->get();
// 对于load指令变量用最新的那个
if (instr->isLoad()) {
auto val = instr->getOperand(0);
if (!(isArr(val) || isGlobal(val))) {
if (!stacks[val].empty()) {
instr->replaceOperand(0, stacks[val].top());
}
}
}
// 然后对于define的情况看alloca、store和phi指令
if (instr->isDefine()) {
if (instr->isAlloca()) {
// alloca指令名字不改了命名就按xx_1x_2...来就行
auto val = instr;
if (!(isArr(val) || isGlobal(val))) {
++valPop[val];
stacks[val].push(val);
++count[val];
}
} else if (instr->isPhi()) {
// Phi指令也是一条特殊的define指令
auto val = dynamic_cast<PhiInst *>(instr)->getMapVal();
if (!(isArr(val) || isGlobal(val))) {
auto i = count[val];
if (i == 0) {
// 对还未alloca就有phi的指令的处理直接删除
usedelete(iter->get());
iter = instrs.erase(iter);
continue;
}
auto newname = dynamic_cast<Instruction *>(val)->getName() + "_" + std::to_string(i);
auto newalloca = pBuilder->createAllocaInstWithoutInsert(val->getType(), {}, block, newname);
FunctionAnalysisInfo* ParentfuncInfo = controlFlowAnalysis->getFunctionAnalysisInfo(block->getParent());
ParentfuncInfo->addIndirectAlloca(newalloca);
instr->replaceOperand(0, newalloca);
++valPop[val];
stacks[val].push(newalloca);
++count[val];
}
} else {
// store指令看operand的名字我们的实现是规定变量在operand的第二位用一个新的alloca x_i代替
auto val = instr->getOperand(1);
if (!(isArr(val) || isGlobal(val))) {
auto i = count[val];
auto newname = dynamic_cast<Instruction *>(val)->getName() + "_" + std::to_string(i);
auto newalloca = pBuilder->createAllocaInstWithoutInsert(val->getType(), {}, block, newname);
FunctionAnalysisInfo* ParentfuncInfo = controlFlowAnalysis->getFunctionAnalysisInfo(block->getParent());
ParentfuncInfo->addIndirectAlloca(newalloca);
// block->getParent()->addIndirectAlloca(newalloca);
instr->replaceOperand(1, newalloca);
++valPop[val];
stacks[val].push(newalloca);
++count[val];
}
}
}
++iter;
}
// 第二大步把所有CFG中的该块的successor的phi指令的相应operand确定
for (auto succ : block->getSuccessors()) {
auto position = getPredIndex(block, succ);
for (auto &instr : succ->getInstructions()) {
if (instr->isPhi()) {
auto val = dynamic_cast<PhiInst *>(instr.get())->getMapVal();
if (!stacks[val].empty()) {
instr->replaceOperand(position + 1, stacks[val].top());
}
} else {
// phi指令是添加在块的最前面的因此过了之后就不会有phi了直接break
break;
}
}
}
// 第三大步递归支配树的后继支配树才能表示define-use关系
BlockAnalysisInfo* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(block);
for (auto sdom : blockInfo->getSdoms()) {
rename(sdom, count, stacks);
}
// 第四大步遍历块中的所有指令如果涉及到define就弹栈这一步是必要的可以从递归的整体性来思考原因
// 注意这里count没清理因为平级之间计数仍然是一直增加的但是stack要清理因为define-use关系来自直接
// 支配结点而不是平级之间,不清理栈会被污染
// 提前优化知道变量对应的要弹栈的次数就可以了没必要遍历所有instr.
for (auto val_pair : valPop) {
auto val = val_pair.first;
for (int i = 0; i < val_pair.second; ++i) {
stacks[val].pop();
}
}
}
/**
* @brief 重命名所有块
*
* 调用rename自上而下实现所有rename
*
* @param [in] void
* @return 无返回值
*/
auto Mem2Reg::renameAll() -> void {
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
// 对于每个function都要SSA化所以count和stacks定义在这并初始化
std::unordered_map<Value *, int> count;
std::unordered_map<Value *, std::stack<Instruction *>> stacks;
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
for (const auto &map_pair : funcInfo->getValue2DefBlocks()) {
auto val = map_pair.first;
count[val] = 0;
}
rename(func->getEntryBlock(), count, stacks);
}
}
/**
* @brief mem2reg对外的接口
*
* 静态单一赋值 + mem2reg等pass的逻辑组合
*
* @param [in] void
* @return 无返回值
*/
auto Mem2Reg::mem2regPipeline() -> void {
// 首先进行mem2reg的前置分析
controlFlowAnalysis->clear();
controlFlowAnalysis->runControlFlowAnalysis();
// 活跃变量分析
activeVarAnalysis->clear();
dataFlowAnalysisUtils.addBackwardAnalyzer(activeVarAnalysis);
dataFlowAnalysisUtils.backwardAnalyze(pModule);
// 计算所有valueToBlocks的定义映射
computeValue2Blocks();
// SysYPrinter printer(pModule);
// 参考llvm的mem2reg遍在插入phi结点之前先做些优化
preOptimize1();
// printer.printIR();
preOptimize2();
// printer.printIR();
// 优化三 可能会针对局部变量优化而删除整个块的alloca/store
preOptimize3();
//再进行活跃变量分析
// 报错?
// printer.printIR();
dataFlowAnalysisUtils.backwardAnalyze(pModule);
// 为所有变量插入phi结点
insertPhi();
// 重命名
renameAll();
}
/**
* @brief 计算块n是块s的第几个前驱
*
* helperfunction没有返回值但是会将dom和other的交集赋值给dom
*
* @param [in] n 基本块n是s的前驱之一
* @param [in] s 基本块s是n的后继之一
* @return 返回n是s的第几个前驱
*/
auto Mem2Reg::getPredIndex(BasicBlock *n, BasicBlock *s) -> int {
int index = 0;
for (auto elem : s->getPredecessors()) {
if (elem == n) {
break;
}
++index;
}
assert(index < static_cast<int>(s->getPredecessors().size()) && "n is not a predecessor of s.");
return index;
}
/**
* 判断一个value是不是全局变量
*/
auto Mem2Reg::isGlobal(Value *val) -> bool {
auto gval = dynamic_cast<GlobalValue *>(val);
return gval != nullptr;
}
/**
* 判断一个value是不是数组
*/
auto Mem2Reg::isArr(Value *val) -> bool {
auto aval = dynamic_cast<AllocaInst *>(val);
return aval != nullptr && aval->getNumDims() != 0;
}
/**
* 删除一个指令的operand对应的value的该条use
*/
auto Mem2Reg::usedelete(Instruction *instr) -> void {
for (auto &use : instr->getOperands()) {
auto val = use->getValue();
val->removeUse(use);
}
}
} // namespace sysy

129
src/Reg2Mem.cpp Normal file
View File

@@ -0,0 +1,129 @@
#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();
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;
}
}
}
}
}
void Reg2Mem::usedelete(Instruction *instr) {
for (auto &use : instr->getOperands()) {
auto val = use->getValue();
val->removeUse(use);
}
}
} // namespace sysy

View File

@@ -0,0 +1,532 @@
#include "SysYIRAnalyser.h"
#include <iostream>
namespace sysy {
void ControlFlowAnalysis::init() {
// 初始化分析器
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
auto basicBlocks = func->getBasicBlocks();
for (auto &basicBlock : basicBlocks) {
blockAnalysisInfo[basicBlock.get()] = new BlockAnalysisInfo();
blockAnalysisInfo[basicBlock.get()]->clear();
}
functionAnalysisInfo[func] = new FunctionAnalysisInfo();
functionAnalysisInfo[func]->clear();
}
}
void ControlFlowAnalysis::runControlFlowAnalysis() {
// 运行控制流分析
clear(); // 清空之前的分析结果
init(); // 初始化分析器
computeDomNode();
computeDomTree();
computeDomFrontierAllBlk();
}
void ControlFlowAnalysis::intersectOP4Dom(std::unordered_set<BasicBlock *> &dom, const std::unordered_set<BasicBlock *> &other) {
// 计算交集
for (auto it = dom.begin(); it != dom.end();) {
if (other.find(*it) == other.end()) {
// 如果other中没有这个基本块则从dom中删除
it = dom.erase(it);
} else {
++it;
}
}
}
auto ControlFlowAnalysis::findCommonDominator(BasicBlock *a, BasicBlock *b) -> BasicBlock * {
// 查找两个基本块的共同支配结点
while (a != b) {
BlockAnalysisInfo* infoA = blockAnalysisInfo[a];
BlockAnalysisInfo* infoB = blockAnalysisInfo[b];
// 如果深度不同,则向上移动到直接支配结点
// TODO空间换时间倍增优化优先级较低
while (infoA->getDomDepth() > infoB->getDomDepth()) {
a = const_cast<BasicBlock*>(infoA->getIdom());
infoA = blockAnalysisInfo[a];
}
while (infoB->getDomDepth() > infoA->getDomDepth()) {
b = const_cast<BasicBlock*>(infoB->getIdom());
infoB = blockAnalysisInfo[b];
}
if (a == b) break;
a = const_cast<BasicBlock*>(infoA->getIdom());
b = const_cast<BasicBlock*>(infoB->getIdom());
}
return a;
}
void ControlFlowAnalysis::computeDomNode(){
auto &functions = pModule->getFunctions();
// 分析每个函数内的基本块
for (const auto &function : functions) {
auto func = function.second.get();
auto basicBlocks = func->getBasicBlocks();
std::unordered_set<BasicBlock *> domSetTmp;
// 一开始把domSetTmp置为所有block
auto entry_block = func->getEntryBlock();
entry_block->setName("Entry");
blockAnalysisInfo[entry_block]->addDominants(entry_block);
for (auto &basicBlock : basicBlocks) {
domSetTmp.emplace(basicBlock.get());
}
// 初始化
for (auto &basicBlock : basicBlocks) {
if (basicBlock.get() != entry_block) {
blockAnalysisInfo[basicBlock.get()]->setDominants(domSetTmp);
// 先把所有block的必经结点都设为N
}
}
// 支配节点计算公式
//DOM[B]={B} {⋂P∈pred(B) DOM[P]}
// 其中pred(B)是B的所有前驱结点
// 迭代计算支配结点,直到不再变化
// 这里使用迭代法,直到支配结点不再变化
// TODOLengauer-Tarjan 算法可以更高效地计算支配结点
// 或者按照CFG拓扑序遍历效率更高
bool changed = true;
while (changed) {
changed = false;
// 循环非start结点
for (auto &basicBlock : basicBlocks) {
if (basicBlock.get() != entry_block) {
auto olddom =
blockAnalysisInfo[basicBlock.get()]->getDominants();
std::unordered_set<BasicBlock *> dom =
blockAnalysisInfo[basicBlock->getPredecessors().front()]->getDominants();
// 对于每个基本块,计算其支配结点
// 取其前驱结点的支配结点的交集和自己
for (auto pred : basicBlock->getPredecessors()) {
intersectOP4Dom(dom, blockAnalysisInfo[pred]->getDominants());
}
dom.emplace(basicBlock.get());
blockAnalysisInfo[basicBlock.get()]->setDominants(dom);
if (dom != olddom) {
changed = true;
}
}
}
}
}
}
// TODO SEMI-NCA算法改进
void ControlFlowAnalysis::computeDomTree() {
// 构造支配树
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
auto basicBlocks = func->getBasicBlocks();
auto entry_block = func->getEntryBlock();
blockAnalysisInfo[entry_block]->setIdom(entry_block);
blockAnalysisInfo[entry_block]->setDomDepth(0); // 入口块深度为0
bool changed = true;
while (changed) {
changed = false;
for (auto &basicBlock : basicBlocks) {
if (basicBlock.get() == entry_block) continue;
BasicBlock *new_idom = nullptr;
for (auto pred : basicBlock->getPredecessors()) {
// 跳过未处理的前驱
if (blockAnalysisInfo[pred]->getIdom() == nullptr) continue;
// new_idom = (new_idom == nullptr) ? pred : findCommonDominator(new_idom, pred);
if (new_idom == nullptr)
new_idom = pred;
else
new_idom = findCommonDominator(new_idom, pred);
}
// 更新直接支配节点
if (new_idom && new_idom != blockAnalysisInfo[basicBlock.get()]->getIdom()) {
// 移除旧的支配关系
if (blockAnalysisInfo[basicBlock.get()]->getIdom()) {
blockAnalysisInfo[const_cast<BasicBlock*>(blockAnalysisInfo[basicBlock.get()]->getIdom())]->removeSdoms(basicBlock.get());
}
// 设置新的支配关系
// std::cout << "Block: " << basicBlock->getName()
// << " New Idom: " << new_idom->getName() << std::endl;
blockAnalysisInfo[basicBlock.get()]->setIdom(new_idom);
blockAnalysisInfo[new_idom]->addSdoms(basicBlock.get());
// 更新深度 = 直接支配节点深度 + 1
blockAnalysisInfo[basicBlock.get()]->setDomDepth(
blockAnalysisInfo[new_idom]->getDomDepth() + 1);
changed = true;
}
}
}
}
// for (auto &basicBlock : basicBlocks) {
// if (basicBlock.get() != func->getEntryBlock()) {
// auto dominats =
// blockAnalysisInfo[basicBlock.get()]->getDominants();
// bool found = false;
// // 从前驱结点开始寻找直接支配结点
// std::queue<BasicBlock *> q;
// for (auto pred : basicBlock->getPredecessors()) {
// q.push(pred);
// }
// // BFS遍历前驱结点直到找到直接支配结点
// while (!found && !q.empty()) {
// auto curr = q.front();
// q.pop();
// if (curr == basicBlock.get())
// continue;
// if (dominats.count(curr) != 0U) {
// blockAnalysisInfo[basicBlock.get()]->setIdom(curr);
// blockAnalysisInfo[curr]->addSdoms(basicBlock.get());
// found = true;
// } else {
// for (auto pred : curr->getPredecessors()) {
// q.push(pred);
// }
// }
// }
// }
// }
}
// std::unordered_set<BasicBlock *> ControlFlowAnalysis::computeDomFrontier(BasicBlock *block) {
// std::unordered_set<BasicBlock *> ret_list;
// // 计算 localDF
// for (auto local_successor : block->getSuccessors()) {
// if (local_successor->getIdom() != block) {
// ret_list.emplace(local_successor);
// }
// }
// // 计算 upDF
// for (auto up_successor : block->getSdoms()) {
// auto childrenDF = computeDF(up_successor);
// for (auto w : childrenDF) {
// if (block != w->getIdom() || block == w) {
// ret_list.emplace(w);
// }
// }
// }
// return ret_list;
// }
void ControlFlowAnalysis::computeDomFrontierAllBlk() {
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
auto basicBlocks = func->getBasicBlocks();
// 按支配树深度排序(从深到浅)
std::vector<BasicBlock *> orderedBlocks;
for (auto &bb : basicBlocks) {
orderedBlocks.push_back(bb.get());
}
std::sort(orderedBlocks.begin(), orderedBlocks.end(),
[this](BasicBlock *a, BasicBlock *b) {
return blockAnalysisInfo[a]->getDomDepth() > blockAnalysisInfo[b]->getDomDepth();
});
// 计算支配边界
for (auto block : orderedBlocks) {
std::unordered_set<BasicBlock *> df;
// Local DF: 直接后继中不被当前块支配的
for (auto succ : block->getSuccessors()) {
// 当前块不支配该后继(即不是其直接支配节点)
if (blockAnalysisInfo[succ]->getIdom() != block) {
df.insert(succ);
}
}
// Up DF: 从支配子树中继承
for (auto child : blockAnalysisInfo[block]->getSdoms()) {
for (auto w : blockAnalysisInfo[child]->getDomFrontiers()) {
// 如果w不被当前块支配
if (block != blockAnalysisInfo[w]->getIdom()) {
df.insert(w);
}
}
}
blockAnalysisInfo[block]->setDomFrontiers(df);
}
}
}
// ==========================
// dataflow analysis utils
// ==========================
// 先引用学长的代码
// TODO: Worklist 增加逆后序遍历机制
void DataFlowAnalysisUtils::forwardAnalyze(Module *pModule){
std::map<DataFlowAnalysis *, bool> workAnalysis;
for (auto &dataflow : forwardAnalysisList) {
dataflow->init(pModule);
}
for (const auto &function : pModule->getFunctions()) {
for (auto &dataflow : forwardAnalysisList) {
workAnalysis.emplace(dataflow, false);
}
while (!workAnalysis.empty()) {
for (const auto &block : function.second->getBasicBlocks()) {
for (auto &elem : workAnalysis) {
if (elem.first->analyze(pModule, block.get())) {
elem.second = true;
}
}
}
std::map<DataFlowAnalysis *, bool> tmp;
std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()),
[](const std::pair<DataFlowAnalysis *, bool> &elem) -> bool { return !elem.second; });
workAnalysis.swap(tmp);
for (auto &elem : workAnalysis) {
elem.second = false;
}
}
}
}
void DataFlowAnalysisUtils::backwardAnalyze(Module *pModule) {
std::map<DataFlowAnalysis *, bool> workAnalysis;
for (auto &dataflow : backwardAnalysisList) {
dataflow->init(pModule);
}
for (const auto &function : pModule->getFunctions()) {
for (auto &dataflow : backwardAnalysisList) {
workAnalysis.emplace(dataflow, false);
}
while (!workAnalysis.empty()) {
for (const auto &block : function.second->getBasicBlocks()) {
for (auto &elem : workAnalysis) {
if (elem.first->analyze(pModule, block.get())) {
elem.second = true;
}
}
}
std::map<DataFlowAnalysis *, bool> tmp;
std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()),
[](const std::pair<DataFlowAnalysis *, bool> &elem) -> bool { return !elem.second; });
workAnalysis.swap(tmp);
for (auto &elem : workAnalysis) {
elem.second = false;
}
}
}
}
std::set<User *> ActiveVarAnalysis::getUsedSet(Instruction *inst) {
using Kind = Instruction::Kind;
std::vector<User *> operands;
for (const auto &operand : inst->getOperands()) {
operands.emplace_back(dynamic_cast<User *>(operand->getValue()));
}
std::set<User *> result;
switch (inst->getKind()) {
// phi op
case Kind::kPhi:
case Kind::kCall:
result.insert(std::next(operands.begin()), operands.end());
break;
case Kind::kCondBr:
result.insert(operands[0]);
break;
case Kind::kBr:
case Kind::kAlloca:
break;
// mem op
case Kind::kStore:
// StoreInst 的第一个操作数是被存储的值,第二个操作数是存储的变量
// 后续的是可能的数组维度
result.insert(operands[0]);
result.insert(operands.begin() + 2, operands.end());
break;
case Kind::kLoad:
case Kind::kLa: {
auto variable = dynamic_cast<AllocaInst *>(operands[0]);
auto global = dynamic_cast<GlobalValue *>(operands[0]);
auto constArray = dynamic_cast<ConstantVariable *>(operands[0]);
if ((variable != nullptr && variable->getNumDims() == 0) || (global != nullptr && global->getNumDims() == 0) ||
(constArray != nullptr && constArray->getNumDims() == 0)) {
result.insert(operands[0]);
}
result.insert(std::next(operands.begin()), operands.end());
break;
}
case Kind::kGetSubArray: {
for (unsigned i = 2; i < operands.size(); i++) {
// 数组的维度信息
result.insert(operands[i]);
}
break;
}
case Kind::kMemset: {
result.insert(std::next(operands.begin()), operands.end());
break;
}
case Kind::kInvalid:
// Binary
case Kind::kAdd:
case Kind::kSub:
case Kind::kMul:
case Kind::kDiv:
case Kind::kRem:
case Kind::kICmpEQ:
case Kind::kICmpNE:
case Kind::kICmpLT:
case Kind::kICmpLE:
case Kind::kICmpGT:
case Kind::kICmpGE:
case Kind::kFAdd:
case Kind::kFSub:
case Kind::kFMul:
case Kind::kFDiv:
case Kind::kFCmpEQ:
case Kind::kFCmpNE:
case Kind::kFCmpLT:
case Kind::kFCmpLE:
case Kind::kFCmpGT:
case Kind::kFCmpGE:
case Kind::kAnd:
case Kind::kOr:
// Unary
case Kind::kNeg:
case Kind::kNot:
case Kind::kFNot:
case Kind::kFNeg:
case Kind::kFtoI:
case Kind::kItoF:
// terminator
case Kind::kReturn:
result.insert(operands.begin(), operands.end());
break;
default:
assert(false);
break;
}
result.erase(nullptr);
return result;
}
User * ActiveVarAnalysis::getDefine(Instruction *inst) {
User *result = nullptr;
if (inst->isStore()) {
StoreInst* store = dynamic_cast<StoreInst *>(inst);
auto operand = store->getPointer();
AllocaInst* variable = dynamic_cast<AllocaInst *>(operand);
GlobalValue* global = dynamic_cast<GlobalValue *>(operand);
if ((variable != nullptr && variable->getNumDims() != 0) || (global != nullptr && global->getNumDims() != 0)) {
// 如果是数组变量或者全局变量,则不返回定义
// TODO兼容数组变量
result = nullptr;
} else {
result = dynamic_cast<User *>(operand);
}
} else if (inst->isPhi()) {
result = dynamic_cast<User *>(inst->getOperand(0));
} else if (inst->isBinary() || inst->isUnary() || inst->isCall() ||
inst->isLoad() || inst->isLa()) {
result = dynamic_cast<User *>(inst);
}
return result;
}
void ActiveVarAnalysis::init(Module *pModule) {
for (const auto &function : pModule->getFunctions()) {
for (const auto &block : function.second->getBasicBlocks()) {
activeTable.emplace(block.get(), std::vector<std::set<User *>>{});
for (unsigned i = 0; i < block->getNumInstructions() + 1; i++)
activeTable.at(block.get()).emplace_back();
}
}
}
// 活跃变量分析公式 每个块内的分析动作供分析器调用
bool ActiveVarAnalysis::analyze(Module *pModule, BasicBlock *block) {
bool changed = false; // 标记数据流结果是否有变化
std::set<User *> activeSet{}; // 当前计算的活跃变量集合
// 步骤1: 计算基本块出口的活跃变量集 (OUT[B])
// 公式: OUT[B] = _{S ∈ succ(B)} IN[S]
for (const auto &succ : block->getSuccessors()) {
// 获取后继块入口的活跃变量集 (IN[S])
auto succActiveSet = activeTable.at(succ).front();
// 合并所有后继块的入口活跃变量
activeSet.insert(succActiveSet.begin(), succActiveSet.end());
}
// 步骤2: 处理基本块出口处的活跃变量集
const auto &instructions = block->getInstructions();
const auto numInstructions = instructions.size();
// 获取旧的出口活跃变量集 (block出口对应索引numInstructions)
const auto &oldEndActiveSet = activeTable.at(block)[numInstructions];
// 检查出口活跃变量集是否有变化
if (!std::equal(activeSet.begin(), activeSet.end(),
oldEndActiveSet.begin(), oldEndActiveSet.end()))
{
changed = true; // 标记变化
activeTable.at(block)[numInstructions] = activeSet; // 更新出口活跃变量集
}
// 步骤3: 逆序遍历基本块中的指令
// 从最后一条指令开始向前计算每个程序点的活跃变量
auto instructionIter = instructions.end();
instructionIter--; // 指向最后一条指令
// 从出口向入口遍历 (索引从numInstructions递减到1)
for (unsigned i = numInstructions; i > 0; i--) {
auto inst = instructionIter->get(); // 当前指令
auto used = getUsedSet(inst);
User *defined = getDefine(inst);
// 步骤3.3: 计算指令入口的活跃变量 (IN[i])
// 公式: IN[i] = use_i (OUT[i] - def_i)
activeSet.erase(defined); // 移除被定义的变量 (OUT[i] - def_i)
activeSet.insert(used.begin(), used.end()); // 添加使用的变量
// 获取旧的入口活跃变量集 (位置i-1对应当前指令的入口)
const auto &oldActiveSet = activeTable.at(block)[i - 1];
// 检查活跃变量集是否有变化
if (!std::equal(activeSet.begin(), activeSet.end(),
oldActiveSet.begin(), oldActiveSet.end()))
{
changed = true; // 标记变化
activeTable.at(block)[i - 1] = activeSet; // 更新入口活跃变量集
}
instructionIter--; // 移动到前一条指令
}
return changed; // 返回数据流结果是否变化
}
auto ActiveVarAnalysis::getActiveTable() const -> const std::map<BasicBlock *, std::vector<std::set<User *>>> & {
return activeTable;
}
} // namespace sysy

View File

@@ -264,7 +264,7 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
dims.push_back(std::any_cast<Value *>(visitExp(exp)));
}
User* variable = module->getVariable(name);
auto variable = module->getVariable(name);
Value* value = std::any_cast<Value *>(visitExp(ctx->exp()));
Type* variableType = dynamic_cast<PointerType *>(variable->getType())->getBaseType();

View File

@@ -438,14 +438,15 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kPhi: {
auto phiInst = dynamic_cast<PhiInst *>(pInst);
std::cout << "%" << phiInst->getName() << " = phi ";
printValue(phiInst->getOperand(0));
std::cout << " = phi ";
printType(phiInst->getType());
for (unsigned i = 0; i < phiInst->getNumOperands(); i += 2) {
for (unsigned i = 1; i < phiInst->getNumOperands(); i++) {
if (i > 0) std::cout << ", ";
std::cout << "[ ";
printValue(phiInst->getOperand(i));
std::cout << ", %" << dynamic_cast<BasicBlock*>(phiInst->getOperand(i+1))->getName() << " ]";
std::cout << " ]";
}
std::cout << std::endl;
} break;

View File

@@ -0,0 +1,37 @@
#pragma once
#include "IR.h"
#include "SysYIRAnalyser.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); // 消除冗余加载和存储
bool isGlobal(Value *val);
bool isArr(Value *val);
void usedelete(Instruction *instr);
};
} // namespace sysy

View File

@@ -263,7 +263,7 @@ class IRBuilder {
auto inst = new AllocaInst(type, dims, parent, name);
assert(inst);
return inst;
} ///< 创建不插入指令列表的分配指令
} ///< 创建不插入指令列表的分配指令[仅用于phi指令]
LoadInst * createLoadInst(Value *pointer, const std::vector<Value *> &indices = {}, const std::string &name = "") {
std::string newName;
if (name.empty()) {

View File

@@ -0,0 +1,59 @@
#pragma once
#include <list>
#include <memory>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include "IR.h"
#include "IRBuilder.h"
#include "SysYIRAnalyser.h"
namespace sysy {
/**
* 实现静态单变量赋值核心类 mem2reg
*/
class Mem2Reg {
private:
Module *pModule;
IRBuilder *pBuilder;
ControlFlowAnalysis *controlFlowAnalysis; // 控制流分析
ActiveVarAnalysis *activeVarAnalysis; // 活跃变量分析
DataFlowAnalysisUtils dataFlowAnalysisUtils;
public:
Mem2Reg(Module *pMoudle, IRBuilder *pBuilder,
ControlFlowAnalysis *pCFA = nullptr, ActiveVarAnalysis *pAVA = nullptr) :
pModule(pMoudle), pBuilder(pBuilder), controlFlowAnalysis(pCFA), activeVarAnalysis(pAVA), dataFlowAnalysisUtils()
{} // 初始化函数
void mem2regPipeline(); ///< mem2reg
private:
// phi节点的插入需要计算IDF
std::unordered_set<BasicBlock *> computeIterDf(const std::unordered_set<BasicBlock *> &blocks); ///< 计算定义块集合的迭代支配边界
auto computeValue2Blocks() -> void; ///< 计算value2block的映射(不包括数组和global)
auto preOptimize1() -> void; ///< llvm memtoreg预优化1: 删除不含load的alloc和store
auto preOptimize2() -> void; ///< llvm memtoreg预优化2: 针对某个变量的Defblocks只有一个块的情况
auto preOptimize3() -> void; ///< llvm memtoreg预优化3: 针对某个变量的所有读写都在同一个块中的情况
auto insertPhi() -> void; ///< 为所有变量的迭代支配边界插入phi结点
auto rename(BasicBlock *block, std::unordered_map<Value *, int> &count,
std::unordered_map<Value *, std::stack<Instruction *>> &stacks) -> void; ///< 单个块的重命名
auto renameAll() -> void; ///< 重命名所有块
// private helper function.
private:
auto getPredIndex(BasicBlock *n, BasicBlock *s) -> int; ///< 获取前驱索引
auto cascade(Instruction *instr, bool &changed, Function *func, BasicBlock *block,
std::list<std::unique_ptr<Instruction>> &instrs) -> void; ///< 消除级联关系
auto isGlobal(Value *val) -> bool; ///< 判断是否是全局变量
auto isArr(Value *val) -> bool; ///< 判断是否是数组
auto usedelete(Instruction *instr) -> void; ///< 删除指令相关的value-use-user关系
};
} // namespace sysy

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

@@ -0,0 +1,23 @@
#pragma once
#include "IR.h"
#include "IRBuilder.h"
namespace sysy {
/**
* Reg2Mem(后端未做phi指令翻译)
*/
class Reg2Mem {
private:
Module *pModule;
IRBuilder *pBuilder;
public:
Reg2Mem(Module *pMoudle, IRBuilder *pBuilder) : pModule(pMoudle), pBuilder(pBuilder) {}
void DeletePhiInst();
// 删除UD关系, 因为删除了phi指令会修改ud关系
void usedelete(Instruction *instr);
};
} // namespace sysy

View File

@@ -0,0 +1,465 @@
#pragma once
#include "IR.h"
namespace sysy {
// 前向声明
class Loop;
// 基本块分析信息类
class BlockAnalysisInfo {
public:
using block_list = std::vector<BasicBlock*>;
using block_set = std::unordered_set<BasicBlock*>;
protected:
// 支配树相关
int domdepth = 0; ///< 支配节点所在深度
BasicBlock* idom = nullptr; ///< 直接支配结点
block_list sdoms; ///< 支配树后继
block_set dominants; ///< 必经结点集合
block_set dominant_frontiers; ///< 支配边界
// 后续添加循环分析相关
// Loop* loopbelong = nullptr; ///< 所属循环
// int loopdepth = 0; ///< 循环深度
public:
// getterface
const int getDomDepth() const { return domdepth; }
const BasicBlock* getIdom() const { return idom; }
const block_list& getSdoms() const { return sdoms; }
const block_set& getDominants() const { return dominants; }
const block_set& getDomFrontiers() const { return dominant_frontiers; }
// 支配树操作
void setDomDepth(int depth) { domdepth = depth; }
void setIdom(BasicBlock* block) { idom = block; }
void addSdoms(BasicBlock* block) { sdoms.push_back(block); }
void clearSdoms() { sdoms.clear(); }
void removeSdoms(BasicBlock* block) {
sdoms.erase(std::remove(sdoms.begin(), sdoms.end(), block), sdoms.end());
}
void addDominants(BasicBlock* block) { dominants.emplace(block); }
void addDominants(const block_set& blocks) { dominants.insert(blocks.begin(), blocks.end()); }
void setDominants(BasicBlock* block) {
dominants.clear();
addDominants(block);
}
void setDominants(const block_set& doms) {
dominants = doms;
}
void setDomFrontiers(const block_set& df) {
dominant_frontiers = df;
}
// TODO循环分析操作方法
// 清空所有分析信息
void clear() {
domdepth = -1;
idom = nullptr;
sdoms.clear();
dominants.clear();
dominant_frontiers.clear();
// loopbelong = nullptr;
// loopdepth = 0;
}
};
// 函数分析信息类
class FunctionAnalysisInfo {
public:
// 函数属性
enum FunctionAttribute : uint64_t {
PlaceHolder = 0x0UL,
Pure = 0x1UL << 0,
SelfRecursive = 0x1UL << 1,
SideEffect = 0x1UL << 2,
NoPureCauseMemRead = 0x1UL << 3
};
// 数据结构
using Loop_list = std::list<std::unique_ptr<Loop>>;
using block_loop_map = std::unordered_map<BasicBlock*, Loop*>;
using value_block_map = std::unordered_map<Value*, BasicBlock*>;
using value_block_count_map = std::unordered_map<Value*, std::unordered_map<BasicBlock*, int>>;
// 分析数据
FunctionAttribute attribute = PlaceHolder; ///< 函数属性
std::set<Function*> callees; ///< 函数调用集合
Loop_list loops; ///< 所有循环
Loop_list topLoops; ///< 顶层循环
// block_loop_map basicblock2Loop; ///< 基本块到循环映射
std::list<std::unique_ptr<AllocaInst>> indirectAllocas; ///< 间接分配内存
// 值定义/使用信息
value_block_map value2AllocBlocks; ///< 值分配位置映射
value_block_count_map value2DefBlocks; ///< 值定义位置映射
value_block_count_map value2UseBlocks; ///< 值使用位置映射
// 函数属性操作
FunctionAttribute getAttribute() const { return attribute; }
void setAttribute(FunctionAttribute attr) { attribute = static_cast<FunctionAttribute>(attribute | attr); }
void clearAttribute() { attribute = PlaceHolder; }
// 调用关系操作
void addCallee(Function* callee) { callees.insert(callee); }
void removeCallee(Function* callee) { callees.erase(callee); }
void clearCallees() { callees.clear(); }
// 值-块映射操作
BasicBlock* getAllocBlockByValue(Value* value) {
auto it = value2AllocBlocks.find(value);
return it != value2AllocBlocks.end() ? it->second : nullptr;
}
std::unordered_set<BasicBlock *> getDefBlocksByValue(Value *value) {
std::unordered_set<BasicBlock *> blocks;
if (value2DefBlocks.count(value) > 0) {
for (const auto &pair : value2DefBlocks[value]) {
blocks.insert(pair.first);
}
}
return blocks;
}
std::unordered_set<BasicBlock *> getUseBlocksByValue(Value *value) {
std::unordered_set<BasicBlock *> blocks;
if (value2UseBlocks.count(value) > 0) {
for (const auto &pair : value2UseBlocks[value]) {
blocks.insert(pair.first);
}
}
return blocks;
}
// 值定义/使用操作
void addValue2AllocBlocks(Value* value, BasicBlock* block) { value2AllocBlocks[value] = block; }
void addValue2DefBlocks(Value* value, BasicBlock* block) { ++value2DefBlocks[value][block]; }
void addValue2UseBlocks(Value* value, BasicBlock* block) { ++value2UseBlocks[value][block]; }
// 获取值定义/使用信息
std::unordered_map<Value *, BasicBlock *>& getValue2AllocBlocks() {
return value2AllocBlocks;
}
std::unordered_map<Value *, std::unordered_map<BasicBlock *, int>>& getValue2DefBlocks() {
return value2DefBlocks;
}
std::unordered_map<Value *, std::unordered_map<BasicBlock *, int>>& getValue2UseBlocks() {
return value2UseBlocks;
}
std::unordered_set<Value *> getValuesOfDefBlock() {
std::unordered_set<Value *> values;
for (const auto &pair : value2DefBlocks) {
values.insert(pair.first);
}
return values;
}
// 删除信息操作
void removeValue2AllocBlock(Value *value) { value2AllocBlocks.erase(value); }
bool removeValue2DefBlock(Value *value, BasicBlock *block) {
bool changed = false;
if (--value2DefBlocks[value][block] == 0) {
value2DefBlocks[value].erase(block);
if (value2DefBlocks[value].empty()) {
value2DefBlocks.erase(value);
changed = true;
}
}
return changed;
}
bool removeValue2UseBlock(Value *value, BasicBlock *block) {
bool changed = false;
if (--value2UseBlocks[value][block] == 0) {
value2UseBlocks[value].erase(block);
if (value2UseBlocks[value].empty()) {
value2UseBlocks.erase(value);
changed = true;
}
}
return changed;
}
// 间接分配操作
void addIndirectAlloca(AllocaInst* alloca) { indirectAllocas.emplace_back(alloca); }
std::list<std::unique_ptr<AllocaInst>>& getIndirectAllocas() { return indirectAllocas; }
// TODO循环分析操作
// 清空所有分析信息
void clear() {
attribute = PlaceHolder;
callees.clear();
loops.clear();
topLoops.clear();
// basicblock2Loop.clear();
indirectAllocas.clear();
value2AllocBlocks.clear();
value2DefBlocks.clear();
value2UseBlocks.clear();
}
};
// 循环类 - 未实现优化
class Loop {
public:
using block_list = std::vector<BasicBlock *>;
using block_set = std::unordered_set<BasicBlock *>;
using Loop_list = std::vector<Loop *>;
protected:
Function *parent; // 所属函数
block_list blocksInLoop; // 循环内的基本块
BasicBlock *preheaderBlock = nullptr; // 前驱块
BasicBlock *headerBlock = nullptr; // 循环头
block_list latchBlock; // 回边块
block_set exitingBlocks; // 退出块
block_set exitBlocks; // 退出目标块
Loop *parentloop = nullptr; // 父循环
Loop_list subLoops; // 子循环
size_t loopID; // 循环ID
unsigned loopDepth; // 循环深度
Instruction *indCondVar = nullptr; // 循环条件变量
Instruction::Kind IcmpKind; // 比较类型
Value *indEnd = nullptr; // 循环结束值
AllocaInst *IndPhi = nullptr; // 循环变量
ConstantValue *indBegin = nullptr; // 循环起始值
ConstantValue *indStep = nullptr; // 循环步长
std::set<GlobalValue *> GlobalValuechange; // 循环内改变的全局变量
int StepType = 0; // 循环步长类型
bool parallelable = false; // 是否可并行
public:
explicit Loop(BasicBlock *header, const std::string &name = "")
: headerBlock(header) {
blocksInLoop.push_back(header);
}
void setloopID() {
static unsigned loopCount = 0;
loopCount = loopCount + 1;
loopID = loopCount;
}
ConstantValue* getindBegin() { return indBegin; }
ConstantValue* getindStep() { return indStep; }
void setindBegin(ConstantValue *indBegin2set) { indBegin = indBegin2set; }
void setindStep(ConstantValue *indStep2set) { indStep = indStep2set; }
void setStepType(int StepType2Set) { StepType = StepType2Set; }
int getStepType() { return StepType; }
size_t getLoopID() { return loopID; }
BasicBlock* getHeader() const { return headerBlock; }
BasicBlock* getPreheaderBlock() const { return preheaderBlock; }
block_list& getLatchBlocks() { return latchBlock; }
block_set& getExitingBlocks() { return exitingBlocks; }
block_set& getExitBlocks() { return exitBlocks; }
Loop* getParentLoop() const { return parentloop; }
void setParentLoop(Loop *parent) { parentloop = parent; }
void addBasicBlock(BasicBlock *bb) { blocksInLoop.push_back(bb); }
void addSubLoop(Loop *loop) { subLoops.push_back(loop); }
void setLoopDepth(unsigned depth) { loopDepth = depth; }
block_list& getBasicBlocks() { return blocksInLoop; }
Loop_list& getSubLoops() { return subLoops; }
unsigned getLoopDepth() const { return loopDepth; }
bool isLoopContainsBasicBlock(BasicBlock *bb) const {
return std::find(blocksInLoop.begin(), blocksInLoop.end(), bb) != blocksInLoop.end();
}
void addExitingBlock(BasicBlock *bb) { exitingBlocks.insert(bb); }
void addExitBlock(BasicBlock *bb) { exitBlocks.insert(bb); }
void addLatchBlock(BasicBlock *bb) { latchBlock.push_back(bb); }
void setPreheaderBlock(BasicBlock *bb) { preheaderBlock = bb; }
void setIndexCondInstr(Instruction *instr) { indCondVar = instr; }
void setIcmpKind(Instruction::Kind kind) { IcmpKind = kind; }
Instruction::Kind getIcmpKind() const { return IcmpKind; }
bool isSimpleLoopInvariant(Value *value) ;
void setIndEnd(Value *value) { indEnd = value; }
void setIndPhi(AllocaInst *phi) { IndPhi = phi; }
Value* getIndEnd() const { return indEnd; }
AllocaInst* getIndPhi() const { return IndPhi; }
Instruction* getIndCondVar() const { return indCondVar; }
void addGlobalValuechange(GlobalValue *globalvaluechange2add) {
GlobalValuechange.insert(globalvaluechange2add);
}
std::set<GlobalValue *>& getGlobalValuechange() {
return GlobalValuechange;
}
void setParallelable(bool flag) { parallelable = flag; }
bool isParallelable() const { return parallelable; }
};
// 控制流分析类
class ControlFlowAnalysis {
private:
Module *pModule; ///< 模块
std::unordered_map<BasicBlock*, BlockAnalysisInfo*> blockAnalysisInfo; // 基本块分析信息表
std::unordered_map<Function*, FunctionAnalysisInfo*> functionAnalysisInfo; // 函数分析信息
public:
explicit ControlFlowAnalysis(Module *pMoudle) : pModule(pMoudle) {}
// 获取基本块分析信息
BlockAnalysisInfo* getBlockAnalysisInfo(BasicBlock *block) {
auto it = blockAnalysisInfo.find(block);
if (it != blockAnalysisInfo.end()) {
return it->second;
}
return nullptr; // 如果未找到返回nullptr
}
FunctionAnalysisInfo* getFunctionAnalysisInfo(Function *func) {
auto it = functionAnalysisInfo.find(func);
if (it != functionAnalysisInfo.end()) {
return it->second;
}
return nullptr; // 如果未找到返回nullptr
}
void init(); // 初始化分析器
void computeDomNode(); // 计算必经结点
void computeDomTree(); // 构造支配树
// std::unordered_set<BasicBlock *> computeDomFrontier(BasicBlock *block) ; // 计算单个块的支配边界(弃用)
void computeDomFrontierAllBlk(); // 计算所有块的支配边界
void runControlFlowAnalysis(); // 运行控制流分析(主要是支配树和支配边界)
void clear(){
for (auto &pair : blockAnalysisInfo) {
delete pair.second; // 清理基本块分析信息
}
blockAnalysisInfo.clear();
for (auto &pair : functionAnalysisInfo) {
delete pair.second; // 清理函数分析信息
}
functionAnalysisInfo.clear();
} // 清空分析结果
~ControlFlowAnalysis() {
clear(); // 析构时清理所有分析信息
}
private:
void intersectOP4Dom(std::unordered_set<BasicBlock *> &dom, const std::unordered_set<BasicBlock *> &other); // 交集运算,
BasicBlock* findCommonDominator(BasicBlock *a, BasicBlock *b); // 查找两个基本块的共同支配结点
};
// 数据流分析类
// 该类为抽象类,具体的数据流分析器需要继承此类
// 因为每个数据流分析器的分析动作都不一样所以需要继承并实现analyze方法
class DataFlowAnalysis {
public:
virtual ~DataFlowAnalysis() = default;
public:
virtual void init(Module *pModule) {} ///< 分析器初始化
virtual auto analyze(Module *pModule, BasicBlock *block) -> bool { return true; } ///< 分析动作若完成则返回true;
virtual void clear() {} ///< 清空
};
// 数据流分析工具类
// 该类用于管理多个数据流分析器,提供统一的前向与后向分析接口
class DataFlowAnalysisUtils {
private:
std::vector<DataFlowAnalysis *> forwardAnalysisList; ///< 前向分析器列表
std::vector<DataFlowAnalysis *> backwardAnalysisList; ///< 后向分析器列表
public:
DataFlowAnalysisUtils() = default;
~DataFlowAnalysisUtils() {
clear(); // 析构时清理所有分析器
}
// 统一添加接口
void addAnalyzers(
std::vector<DataFlowAnalysis *> forwardList,
std::vector<DataFlowAnalysis *> backwardList = {})
{
forwardAnalysisList.insert(
forwardAnalysisList.end(),
forwardList.begin(),
forwardList.end());
backwardAnalysisList.insert(
backwardAnalysisList.end(),
backwardList.begin(),
backwardList.end());
}
// 单独添加接口
void addForwardAnalyzer(DataFlowAnalysis *analyzer) {
forwardAnalysisList.push_back(analyzer);
}
void addBackwardAnalyzer(DataFlowAnalysis *analyzer) {
backwardAnalysisList.push_back(analyzer);
}
// 设置分析器列表
void setAnalyzers(
std::vector<DataFlowAnalysis *> forwardList,
std::vector<DataFlowAnalysis *> backwardList)
{
forwardAnalysisList = std::move(forwardList);
backwardAnalysisList = std::move(backwardList);
}
// 清空列表
void clear() {
forwardAnalysisList.clear();
backwardAnalysisList.clear();
}
// 访问器
const auto& getForwardAnalyzers() const { return forwardAnalysisList; }
const auto& getBackwardAnalyzers() const { return backwardAnalysisList; }
public:
void forwardAnalyze(Module *pModule); ///< 执行前向分析
void backwardAnalyze(Module *pModule); ///< 执行后向分析
};
// 活跃变量分析类
// 提供def - use分析
// 未兼容数组变量但是考虑了维度的use信息
class ActiveVarAnalysis : public DataFlowAnalysis {
private:
std::map<BasicBlock *, std::vector<std::set<User *>>> activeTable; ///< 活跃信息表,存储每个基本块内的的活跃变量信息
public:
ActiveVarAnalysis() = default;
~ActiveVarAnalysis() override = default;
public:
static std::set<User*> getUsedSet(Instruction *inst);
static User* getDefine(Instruction *inst);
public:
void init(Module *pModule) override;
bool analyze(Module *pModule, BasicBlock *block) override;
// 外部活跃信息表访问器
const std::map<BasicBlock *, std::vector<std::set<User *>>> &getActiveTable() const;
void clear() override {
activeTable.clear(); // 清空活跃信息表
}
};
// 分析管理器 后续实现
// class AnalysisManager {
// };
} // namespace sysy

View File

@@ -11,6 +11,10 @@ using namespace antlr4;
#include "SysYIRPrinter.h"
#include "SysYIROptPre.h"
#include "RISCv64Backend.h"
#include "SysYIRAnalyser.h"
#include "DeadCodeElimination.h"
#include "Mem2Reg.h"
#include "Reg2Mem.h"
// #include "LLVMIRGenerator.h"
using namespace sysy;
@@ -83,6 +87,23 @@ int main(int argc, char **argv) {
auto builder = generator.getBuilder();
SysYOptPre optPre(moduleIR, builder);
optPre.SysYOptimizateAfterIR();
ControlFlowAnalysis cfa(moduleIR);
cfa.init();
ActiveVarAnalysis ava;
ava.init(moduleIR);
printer.printIR();
DeadCodeElimination dce(moduleIR, &cfa, &ava);
dce.runDCEPipeline();
Mem2Reg mem2reg(moduleIR, builder, &cfa, &ava);
mem2reg.mem2regPipeline();
printer.printIR();
Reg2Mem reg2mem(moduleIR, builder);
reg2mem.DeletePhiInst();
printer.printIR();
dce.runDCEPipeline();
return EXIT_SUCCESS;
}