[死代码删除]:保证扩展性、模块化构建死代码删除,包括消除无用store,alloca,load,globalval,mem2reg引入的无用alloca以及reg2mem导致的store-load-store冗余存储
This commit is contained in:
@@ -19,6 +19,7 @@ add_executable(sysyc
|
|||||||
SysYIRPrinter.cpp
|
SysYIRPrinter.cpp
|
||||||
SysYIROptPre.cpp
|
SysYIROptPre.cpp
|
||||||
SysYIRAnalyser.cpp
|
SysYIRAnalyser.cpp
|
||||||
|
DeadCodeElimination.cpp
|
||||||
Mem2Reg.cpp
|
Mem2Reg.cpp
|
||||||
Reg2Mem.cpp
|
Reg2Mem.cpp
|
||||||
RISCv32Backend.cpp
|
RISCv32Backend.cpp
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ void DeadCodeElimination::runDCEPipeline() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 消除无用存储 消除条件:
|
||||||
|
// 存储的目标指针(pointer)不是全局变量(!isGlobal(pointer))。
|
||||||
|
// 存储的目标指针不是数组参数(!isArr(pointer) 或不在函数参数列表里)。
|
||||||
|
// 该指针的所有使用者(uses)仅限 alloca 或 store(即没有 load 或其他指令使用它)。
|
||||||
void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) {
|
void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) {
|
||||||
for (const auto& block : func->getBasicBlocks()) {
|
for (const auto& block : func->getBasicBlocks()) {
|
||||||
auto& instrs = block->getInstructions();
|
auto& instrs = block->getInstructions();
|
||||||
@@ -31,8 +35,8 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) {
|
|||||||
|
|
||||||
auto storeInst = dynamic_cast<StoreInst*>(inst);
|
auto storeInst = dynamic_cast<StoreInst*>(inst);
|
||||||
auto pointer = storeInst->getPointer();
|
auto pointer = storeInst->getPointer();
|
||||||
if (isGlobal(pointer) ||
|
// 如果是全局变量或者是函数的数组参数
|
||||||
(isArr(pointer) &&
|
if (isGlobal(pointer) || (isArr(pointer) &&
|
||||||
std::find(func->getEntryBlock()->getArguments().begin(),
|
std::find(func->getEntryBlock()->getArguments().begin(),
|
||||||
func->getEntryBlock()->getArguments().end(),
|
func->getEntryBlock()->getArguments().end(),
|
||||||
pointer) != func->getEntryBlock()->getArguments().end())) {
|
pointer) != func->getEntryBlock()->getArguments().end())) {
|
||||||
@@ -40,17 +44,19 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tag = true;
|
bool changetag = true;
|
||||||
for (auto& use : pointer->getUses()) {
|
for (auto& use : pointer->getUses()) {
|
||||||
|
// 依次判断store的指针是否被其他指令使用
|
||||||
auto user = use->getUser();
|
auto user = use->getUser();
|
||||||
auto userInst = dynamic_cast<Instruction*>(user);
|
auto userInst = dynamic_cast<Instruction*>(user);
|
||||||
|
// 如果使用store的指针的指令不是Alloca或Store,则不删除
|
||||||
if (userInst != nullptr && !userInst->isAlloca() && !userInst->isStore()) {
|
if (userInst != nullptr && !userInst->isAlloca() && !userInst->isStore()) {
|
||||||
tag = false;
|
changetag = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag) {
|
if (changetag) {
|
||||||
changed = true;
|
changed = true;
|
||||||
usedelete(storeInst);
|
usedelete(storeInst);
|
||||||
iter = instrs.erase(iter);
|
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) {
|
void DeadCodeElimination::eliminateDeadLoads(Function* func, bool& changed) {
|
||||||
for (const auto& block : func->getBasicBlocks()) {
|
for (const auto& block : func->getBasicBlocks()) {
|
||||||
auto& instrs = block->getInstructions();
|
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) {
|
void DeadCodeElimination::eliminateDeadAllocas(Function* func, bool& changed) {
|
||||||
for (const auto& block : func->getBasicBlocks()) {
|
for (const auto& block : func->getBasicBlocks()) {
|
||||||
auto& instrs = block->getInstructions();
|
auto& instrs = block->getInstructions();
|
||||||
@@ -99,18 +109,23 @@ void DeadCodeElimination::eliminateDeadAllocas(Function* func, bool& changed) {
|
|||||||
++iter;
|
++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) {
|
void DeadCodeElimination::eliminateDeadGlobals(bool& changed) {
|
||||||
auto& globals = pModule->getGlobals();
|
auto& globals = pModule->getGlobals();
|
||||||
for (auto it = globals.begin(); it != globals.end();) {
|
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) {
|
void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool& changed) {
|
||||||
for (const auto& block : func->getBasicBlocks()) {
|
for (const auto& block : func->getBasicBlocks()) {
|
||||||
auto& instrs = block->getInstructions();
|
auto& instrs = block->getInstructions();
|
||||||
@@ -140,12 +159,14 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool&
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// 如果 pointer 仅被该 phi 使用,可以删除 ph
|
||||||
if (tag) {
|
if (tag) {
|
||||||
changed = true;
|
changed = true;
|
||||||
usedelete(inst);
|
usedelete(inst);
|
||||||
iter = instrs.erase(iter);
|
iter = instrs.erase(iter);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// 数组指令还不完善,不保证memset优化效果
|
||||||
} else if (inst->isMemset()) {
|
} else if (inst->isMemset()) {
|
||||||
auto memsetInst = dynamic_cast<MemsetInst*>(inst);
|
auto memsetInst = dynamic_cast<MemsetInst*>(inst);
|
||||||
auto pointer = memsetInst->getPointer();
|
auto pointer = memsetInst->getPointer();
|
||||||
@@ -155,6 +176,52 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool&
|
|||||||
iter = instrs.erase(iter);
|
iter = instrs.erase(iter);
|
||||||
continue;
|
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;
|
++iter;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IR.h"
|
#include "IR.h"
|
||||||
|
#include "SysYIRAnalyser.h"
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
class DeadCodeElimination {
|
class DeadCodeElimination {
|
||||||
private:
|
private:
|
||||||
Module *pModule;
|
Module *pModule;
|
||||||
|
ControlFlowAnalysis *pCFA; // 控制流分析指针
|
||||||
|
ActiveVarAnalysis *pAVA; // 活跃变量分析指针
|
||||||
|
DataFlowAnalysisUtils dataFlowAnalysisUtils; // 数据流分析工具类
|
||||||
|
|
||||||
public:
|
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来运行不同的死代码删除流程
|
// TODO:根据参数传入的passes来运行不同的死代码删除流程
|
||||||
// void runDCEPipeline(const std::vector<std::string>& passes = {
|
// void runDCEPipeline(const std::vector<std::string>& passes = {
|
||||||
@@ -21,6 +27,7 @@ class DeadCodeElimination {
|
|||||||
void eliminateDeadLoads(Function* func, bool& changed); // 消除无用加载
|
void eliminateDeadLoads(Function* func, bool& changed); // 消除无用加载
|
||||||
void eliminateDeadAllocas(Function* func, bool& changed); // 消除无用内存分配
|
void eliminateDeadAllocas(Function* func, bool& changed); // 消除无用内存分配
|
||||||
void eliminateDeadGlobals(bool& changed); // 消除无用全局变量
|
void eliminateDeadGlobals(bool& changed); // 消除无用全局变量
|
||||||
|
void eliminateDeadIndirectiveAllocas(Function* func, bool& changed); // 消除无用间接内存分配(phi节点)
|
||||||
void eliminateDeadRedundantLoadStore(Function* func, bool& changed); // 消除冗余加载和存储
|
void eliminateDeadRedundantLoadStore(Function* func, bool& changed); // 消除冗余加载和存储
|
||||||
bool isGlobal(Value *val);
|
bool isGlobal(Value *val);
|
||||||
bool isArr(Value *val);
|
bool isArr(Value *val);
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ class IRBuilder {
|
|||||||
auto inst = new AllocaInst(type, dims, parent, name);
|
auto inst = new AllocaInst(type, dims, parent, name);
|
||||||
assert(inst);
|
assert(inst);
|
||||||
return inst;
|
return inst;
|
||||||
} ///< 创建不插入指令列表的分配指令
|
} ///< 创建不插入指令列表的分配指令[仅用于phi指令]
|
||||||
LoadInst * createLoadInst(Value *pointer, const std::vector<Value *> &indices = {}, const std::string &name = "") {
|
LoadInst * createLoadInst(Value *pointer, const std::vector<Value *> &indices = {}, const std::string &name = "") {
|
||||||
std::string newName;
|
std::string newName;
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using namespace antlr4;
|
|||||||
#include "SysYIRPrinter.h"
|
#include "SysYIRPrinter.h"
|
||||||
#include "SysYIROptPre.h"
|
#include "SysYIROptPre.h"
|
||||||
#include "SysYIRAnalyser.h"
|
#include "SysYIRAnalyser.h"
|
||||||
|
#include "DeadCodeElimination.h"
|
||||||
#include "Mem2Reg.h"
|
#include "Mem2Reg.h"
|
||||||
#include "Reg2Mem.h"
|
#include "Reg2Mem.h"
|
||||||
// #include "LLVMIRGenerator.h"
|
// #include "LLVMIRGenerator.h"
|
||||||
@@ -86,12 +87,24 @@ int main(int argc, char **argv) {
|
|||||||
auto builder = generator.getBuilder();
|
auto builder = generator.getBuilder();
|
||||||
SysYOptPre optPre(moduleIR, builder);
|
SysYOptPre optPre(moduleIR, builder);
|
||||||
optPre.SysYOptimizateAfterIR();
|
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();
|
mem2reg.mem2regPipeline();
|
||||||
printer.printIR();
|
printer.printIR();
|
||||||
Reg2Mem reg2mem(moduleIR, builder);
|
Reg2Mem reg2mem(moduleIR, builder);
|
||||||
reg2mem.DeletePhiInst();
|
reg2mem.DeletePhiInst();
|
||||||
printer.printIR();
|
printer.printIR();
|
||||||
|
dce.runDCEPipeline();
|
||||||
|
printer.printIR();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|||||||
Reference in New Issue
Block a user