[死代码删除]:保证扩展性、模块化构建死代码删除,包括消除无用store,alloca,load,globalval,mem2reg引入的无用alloca以及reg2mem导致的store-load-store冗余存储

This commit is contained in:
rain2133
2025-06-25 15:33:25 +08:00
parent b12732f10d
commit 0d23475aa1
5 changed files with 108 additions and 20 deletions

View File

@ -19,6 +19,7 @@ add_executable(sysyc
SysYIRPrinter.cpp
SysYIROptPre.cpp
SysYIRAnalyser.cpp
DeadCodeElimination.cpp
Mem2Reg.cpp
Reg2Mem.cpp
RISCv32Backend.cpp

View File

@ -19,6 +19,10 @@ void DeadCodeElimination::runDCEPipeline() {
}
}
// 消除无用存储 消除条件:
// 存储的目标指针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();
@ -31,8 +35,8 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) {
auto storeInst = dynamic_cast<StoreInst*>(inst);
auto pointer = storeInst->getPointer();
if (isGlobal(pointer) ||
(isArr(pointer) &&
// 如果是全局变量或者是函数的数组参数
if (isGlobal(pointer) || (isArr(pointer) &&
std::find(func->getEntryBlock()->getArguments().begin(),
func->getEntryBlock()->getArguments().end(),
pointer) != func->getEntryBlock()->getArguments().end())) {
@ -40,17 +44,19 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) {
continue;
}
bool tag = true;
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()) {
tag = false;
changetag = false;
break;
}
}
if (tag) {
if (changetag) {
changed = true;
usedelete(storeInst);
iter = instrs.erase(iter);
@ -60,7 +66,8 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) {
}
}
}
// 消除无用加载 消除条件:
// 该指令的结果未被使用inst->getUses().empty())。
void DeadCodeElimination::eliminateDeadLoads(Function* func, bool& changed) {
for (const auto& block : func->getBasicBlocks()) {
auto& instrs = block->getInstructions();
@ -79,6 +86,9 @@ void DeadCodeElimination::eliminateDeadLoads(Function* func, bool& changed) {
}
}
// 消除无用加载 消除条件:
// 该 alloca 未被任何指令使用allocaInst->getUses().empty())。
// 该 alloca 不是函数的参数(不在 entry 块的参数列表里)。
void DeadCodeElimination::eliminateDeadAllocas(Function* func, bool& changed) {
for (const auto& block : func->getBasicBlocks()) {
auto& instrs = block->getInstructions();
@ -99,18 +109,23 @@ void DeadCodeElimination::eliminateDeadAllocas(Function* func, bool& changed) {
++iter;
}
}
// for (auto it = func->getIndirectAllocas().begin(); it != func->getIndirectAllocas().end();) {
// auto& allocaInst = *it;
// if (allocaInst->getUses().empty()) {
// changed = true;
// it = func->getIndirectAllocas().erase(it);
// } else {
// ++it;
// }
// }
}
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();) {
@ -124,6 +139,10 @@ void DeadCodeElimination::eliminateDeadGlobals(bool& changed) {
}
}
// 消除冗余加载和存储 消除条件:
// 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();
@ -140,12 +159,14 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool&
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();
@ -155,6 +176,52 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool&
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;
}

View File

@ -1,15 +1,21 @@
#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) : pModule(pMoudle) {} // 初始化函数
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 = {
@ -21,6 +27,7 @@ class DeadCodeElimination {
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);

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

@ -11,6 +11,7 @@ using namespace antlr4;
#include "SysYIRPrinter.h"
#include "SysYIROptPre.h"
#include "SysYIRAnalyser.h"
#include "DeadCodeElimination.h"
#include "Mem2Reg.h"
#include "Reg2Mem.h"
// #include "LLVMIRGenerator.h"
@ -86,12 +87,24 @@ int main(int argc, char **argv) {
auto builder = generator.getBuilder();
SysYOptPre optPre(moduleIR, builder);
optPre.SysYOptimizateAfterIR();
Mem2Reg mem2reg(moduleIR, builder);
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();
printer.printIR();
return EXIT_SUCCESS;
}
return EXIT_SUCCESS;