This commit is contained in:
ridethepig 2023-06-19 16:14:43 +08:00
parent 2ec8ff8ed5
commit 8e570f6b4d
6 changed files with 147 additions and 24 deletions

2
.vscode/launch.json vendored
View File

@ -11,7 +11,7 @@
"program": "${workspaceFolder}/build/sysy",
// "args": ["../sysytests/functional_2021/069_greatest_common_divisor.sy", "-S", "-o", "build/my.s", "-O1", "-emit-llvm"],
// "args" : ["-S", "../sysytests/functional_2022/21_if_test2.sy", "-o", "build/dbg.s", "-emit-llvm", "-O1",],
"args" : ["-S", "../sysytests/functional_h_2022/04_break_continue.sy", "-o", "build/dbg.s", "-emit-llvm", "-O1",],
"args" : ["-S", "../sysytests/functional_h_2022/29_long_line.sy", "-o", "build/dbg.s", "-emit-llvm", "-O1",],
"cwd": "${workspaceFolder}"
},
]

View File

@ -76,4 +76,10 @@ private:
std::set<MInstMove *, MvCmp> active_moves;
};
class PassPeepHole final : public MCPass {
public:
PassPeepHole() : MCPass("peep hole") {}
void run(const MCModule &module) override;
};
} // namespace CompSysY

View File

@ -256,7 +256,8 @@ void CFG::calculate() {
changed = true;
it = node->dom.erase(it);
}
else ++it;
else
++it;
}
}
}

View File

@ -147,7 +147,10 @@ int main(int argc, const char **argv) {
mc_module.MC2ASM(ofs_virt_asm_file, true);
ofs_virt_asm_file.close();
std::vector<sptr(MCPass)> mc_passes = {std::make_shared<PassRegAlloc>()};
std::vector<sptr(MCPass)> mc_passes = {
std::make_shared<PassRegAlloc>(),
std::make_shared<PassPeepHole>(),
};
for (auto pass : mc_passes) {
pass->run(mc_module);
}

View File

@ -45,6 +45,7 @@ void remove_block(sptr(BasicBlock) victim) {
// 高级编译器18.1
bool Elim_Unreach_Code(Function *func) {
LOG(INFO) << "[DCE] Unreachable code elim";
bool again = true;
bool changed = false;
std::unordered_set<BasicBlock *> reachable;
@ -69,6 +70,7 @@ bool Elim_Unreach_Code(Function *func) {
// procedures From Efficiently Computing SSA Form and the Control Dependence Graph, Zadeck 1991
// comp 512 Lecture10 gives a clear description
bool Elim_Dead_Code(Function *func) {
LOG(INFO) << "[DCE] Dead code elim";
CFG RCFG;
RCFG.build_from_func(func, true);
RCFG.calculate();
@ -181,14 +183,12 @@ static void get_post_order(BasicBlock* rt) {
post_order.push_back(rt);
}
// 高级编译器18.2, comp512 Lecture10 gives a clearer version
bool Fuse_Block(Function *func) {
auto is_branch = [](Instruction* inst) {
return dynamic_cast<InstBranch*>(inst) && inst->operand_list.size() == 3;
};
visit.clear(); post_order.clear();
LOG(INFO) << "[DCE] Branch merge";
auto is_branch = [](Instruction *inst) { return dynamic_cast<InstBranch *>(inst) && inst->operand_list.size() == 3; };
visit.clear();
post_order.clear();
get_post_order(func->bb_list.front().get());
for (auto bb : post_order) {
if (is_branch(bb->inst_list.back().get())) {
@ -208,7 +208,8 @@ bool Fuse_Block(Function *func) {
else if (auto inst = dynamic_cast<InstBranch *>(bb->inst_list.back().get())) {
auto target = shared_cast<BasicBlock>(inst->operand_list[0]);
assert(target);
// branch has side-effect on phi nodes, dealing with that is beyond this shabby compiler's capability, thus simply ignore
// branch has side-effect on phi nodes, dealing with that is beyond this shabby compiler's capability, thus simply
// ignore
if (shared_cast<InstPhi>(target->inst_list.front())) continue;
if (bb->inst_list.size() == 1) {
/* bb_i -> bb_j

112
src/pass_peephole.cpp Normal file
View File

@ -0,0 +1,112 @@
#include "mc_pass.h"
namespace CompSysY {
static void peephole(MFunction *func) {
auto check_mv_ident = [](MInstMove *inst) {
if (inst->dst.is_reg() && inst->src.is_reg()) {
if (inst->dst.value == inst->src.value) {
return true;
}
}
return false;
};
auto check_mv_dup = [](MInstMove *inst1, MInstMove *inst2) {
if (inst1->dst.value == inst2->dst.value) {
if (inst1->src.is_reg() && inst2->src.is_reg()) {
// for regs, tags may differ
return inst1->src.value == inst2->src.value;
}
// for imm and glob, compare their tag and value
return inst1->src == inst2->src;
}
return false;
};
auto check_useless_bin = [](MInstBinary *inst) {
if (!inst->op2.is_imm()) return false;
if (inst->op1 != inst->dst) return false;
switch (inst->inst_tag) {
case MInstTag::Add: return inst->op2.value == 0;
case MInstTag::Sub: return inst->op2.value == 0;
case MInstTag::Lsh: return inst->op2.value == 0;
case MInstTag::Rsh: return inst->op2.value == 0;
default: break;
}
return false;
};
auto check_trivial_jmp = [](MInstJump *inst) {
// jump to the next block
auto next_bb = std::next(inst->parent_bb->itr);
if (next_bb != inst->parent_bb->parent_func->bb_list.end()) {
if (inst->target == *next_bb) {
return true;
}
}
return false;
};
auto check_useless_ld = [](MInstLoad *inst_ld, MInstStore *inst_st) {
// load from the same addr after a store can be converted into a mov
if (inst_ld->addr.value == inst_st->addr.value) {
if (inst_ld->offset == inst_st->offset) {
return true;
}
}
return false;
};
for (auto bb : func->bb_list) {
for (auto itr = bb->inst_list.begin(); itr != bb->inst_list.end();) {
auto inst = *itr++;
if (auto inst_mv = shared_cast<MInstMove>(inst)) {
if (check_mv_ident(inst_mv.get())) {
bb->inst_list.erase(inst->itr);
continue;
}
auto next_inst_itr = std::next(inst->itr);
if (next_inst_itr != bb->inst_list.end()) {
if (auto inst_mv2 = shared_cast<MInstMove>(*next_inst_itr)) {
if (check_mv_dup(inst_mv.get(), inst_mv2.get())) {
bb->inst_list.erase(inst->itr);
VLOG(6) << "[PeepHole] remove duplicate move";
}
}
}
}
else if (auto inst_bin = shared_cast<MInstBinary>(inst)) {
if (check_useless_bin(inst_bin.get())) {
bb->inst_list.erase(inst->itr);
VLOG(6) << "[PeepHole] remove identical binary";
}
}
else if (auto inst_jmp = shared_cast<MInstJump>(inst)) {
if (check_trivial_jmp(inst_jmp.get())) {
bb->inst_list.erase(inst->itr);
VLOG(6) << "[PeepHole] remove trivial jump";
}
}
else if (auto inst_ld = shared_cast<MInstLoad>(inst)) {
if (inst_ld->itr == bb->inst_list.begin()) continue;
auto prev_inst = std::prev(inst->itr);
if (auto inst_st = shared_cast<MInstStore>(*prev_inst)) {
if (check_useless_ld(inst_ld.get(), inst_st.get())) {
assert(inst_ld->dst.is_reg() && inst_st->data.is_reg());
if (inst_ld->dst.value != inst_st->data.value) {
auto inst_mv = MInstMove::New(inst_ld, InsertPos::Before);
inst_mv->dst = inst_ld->dst;
inst_mv->src = inst_st->data;
}
bb->inst_list.erase(inst_ld->itr);
VLOG(6) << "[PeepHole] remove trivial load after store";
}
}
}
}
}
}
void PassPeepHole::run(const MCModule &module) {
for (auto func : module.function_list) {
peephole(func.get());
}
}
} // namespace CompSysY