debugging
This commit is contained in:
182
src/DeadCodeElimination.cpp
Normal file
182
src/DeadCodeElimination.cpp
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 tag = true;
|
||||||
|
for (auto& use : pointer->getUses()) {
|
||||||
|
auto user = use->getUser();
|
||||||
|
auto userInst = dynamic_cast<Instruction*>(user);
|
||||||
|
if (userInst != nullptr && !userInst->isAlloca() && !userInst->isStore()) {
|
||||||
|
tag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag) {
|
||||||
|
changed = true;
|
||||||
|
usedelete(storeInst);
|
||||||
|
iter = instrs.erase(iter);
|
||||||
|
} else {
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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::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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tag) {
|
||||||
|
changed = true;
|
||||||
|
usedelete(inst);
|
||||||
|
iter = instrs.erase(iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++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
|
||||||
30
src/include/DeadCodeElimination.h
Normal file
30
src/include/DeadCodeElimination.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IR.h"
|
||||||
|
|
||||||
|
namespace sysy {
|
||||||
|
|
||||||
|
class DeadCodeElimination {
|
||||||
|
private:
|
||||||
|
Module *pModule;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DeadCodeElimination(Module *pMoudle) : pModule(pMoudle) {} // 初始化函数
|
||||||
|
|
||||||
|
// 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 eliminateDeadRedundantLoadStore(Function* func, bool& changed); // 消除冗余加载和存储
|
||||||
|
bool isGlobal(Value *val);
|
||||||
|
bool isArr(Value *val);
|
||||||
|
void usedelete(Instruction *instr);
|
||||||
|
|
||||||
|
};
|
||||||
|
} // namespace sysy
|
||||||
Reference in New Issue
Block a user