Lab4: Implement basic scalar optimizations and lower Phi nodes to assembly
This commit is contained in:
@@ -1,4 +1,75 @@
|
||||
// 死代码删除(DCE):
|
||||
// - 删除无用指令与无用基本块
|
||||
// - 通常与 CFG 简化配合使用
|
||||
#include "ir/PassManager.h"
|
||||
#include <iostream>
|
||||
#include <unordered_set>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
namespace ir {
|
||||
|
||||
bool RunDCE(Function* func) {
|
||||
std::unordered_set<Instruction*> live_instructions;
|
||||
std::queue<Instruction*> worklist;
|
||||
|
||||
// 1. Mark inherently live instructions
|
||||
for (const auto& bbPtr : func->GetBlocks()) {
|
||||
for (const auto& instPtr : bbPtr->GetInstructions()) {
|
||||
auto* inst = instPtr.get();
|
||||
bool inherently_live = false;
|
||||
|
||||
switch (inst->GetOpcode()) {
|
||||
case Opcode::Ret:
|
||||
case Opcode::Br:
|
||||
case Opcode::Store:
|
||||
case Opcode::Call:
|
||||
inherently_live = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (inherently_live) {
|
||||
live_instructions.insert(inst);
|
||||
worklist.push(inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Propagate liveness along the def-use chains
|
||||
while (!worklist.empty()) {
|
||||
auto* inst = worklist.front();
|
||||
worklist.pop();
|
||||
|
||||
for (size_t i = 0; i < inst->GetNumOperands(); ++i) {
|
||||
auto* operand = inst->GetOperand(i);
|
||||
if (auto* op_inst = dynamic_cast<Instruction*>(operand)) {
|
||||
if (live_instructions.find(op_inst) == live_instructions.end()) {
|
||||
live_instructions.insert(op_inst);
|
||||
worklist.push(op_inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Sweep dead instructions
|
||||
bool changed = false;
|
||||
for (const auto& bbPtr : func->GetBlocks()) {
|
||||
std::vector<Instruction*> dead_instructions;
|
||||
for (const auto& instPtr : bbPtr->GetInstructions()) {
|
||||
auto* inst = instPtr.get();
|
||||
if (live_instructions.find(inst) == live_instructions.end()) {
|
||||
dead_instructions.push_back(inst);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dead_instructions.empty()) {
|
||||
changed = true;
|
||||
for (auto* inst : dead_instructions) {
|
||||
bbPtr->EraseInstruction(inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
|
||||
Reference in New Issue
Block a user