From 86a835c6efe003d972f138348c020ef4eecbce1e Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Thu, 24 Oct 2024 06:44:04 +0000 Subject: [PATCH] write DCE --- include/IR/IR_basic.h | 6 +++- include/opt/dce.h | 4 +++ include/opt/opt.h | 3 +- src/main.cpp | 1 + src/opt/dce.cpp | 63 ++++++++++++++++++++++++++++++++++++++++ src/opt/liveanalysis.cpp | 60 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 include/opt/dce.h create mode 100644 src/opt/dce.cpp diff --git a/include/IR/IR_basic.h b/include/IR/IR_basic.h index 14915c9..8defb31 100644 --- a/include/IR/IR_basic.h +++ b/include/IR/IR_basic.h @@ -64,7 +64,11 @@ class GlobalVarDefItem : public LLVMIRItemBase { } } }; -class ActionItem : public LLVMIRItemBase {}; +class ActionItem : public LLVMIRItemBase { + public: + bool marked_as_useless; + ActionItem() : marked_as_useless(false) {} +}; class JMPActionItem : public ActionItem { public: std::shared_ptr corresponding_phi; diff --git a/include/opt/dce.h b/include/opt/dce.h new file mode 100644 index 0000000..497d7bd --- /dev/null +++ b/include/opt/dce.h @@ -0,0 +1,4 @@ +#pragma once +#include "IR/IR_basic.h" + +std::shared_ptr DCE(std::shared_ptr src); \ No newline at end of file diff --git a/include/opt/opt.h b/include/opt/opt.h index 50c4d97..23353c6 100644 --- a/include/opt/opt.h +++ b/include/opt/opt.h @@ -2,4 +2,5 @@ #include "gen.h" #include "global_var_cache.h" #include "mem2reg.h" -#include "regalloc.h" \ No newline at end of file +#include "regalloc.h" +#include "dce.h" \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 6800b1e..1c2b87a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -49,6 +49,7 @@ int main(int argc, char **argv) { auto IR_with_out_allocas = Mem2Reg(IR); // IR_with_out_allocas->RecursivePrint(std::cerr); IR_with_out_allocas = GloabalVarCache(IR_with_out_allocas); + IR_with_out_allocas = DCE(IR_with_out_allocas); // IR_with_out_allocas->RecursivePrint(std::cerr); auto IR_with_out_phis = PhiEliminate(IR_with_out_allocas); // IR_with_out_phis->RecursivePrint(std::cerr); diff --git a/src/opt/dce.cpp b/src/opt/dce.cpp new file mode 100644 index 0000000..8ff3987 --- /dev/null +++ b/src/opt/dce.cpp @@ -0,0 +1,63 @@ +#include "dce.h" +#include "IR/IR_basic.h" +#include "cfg.h" +#include "liveanalysis.h" +void ConductDCEForFunction(std::shared_ptr func); + +void ConductDCEForFunction(std::shared_ptr func) { + CFGType cfg; + cfg = BuildCFGForFunction(func); + LiveAnalysis(cfg); + std::unordered_set all_vars; + std::unordered_map> use_map, def_map; + std::unordered_map> actions_use_vars; + for (size_t i = 0; i < cfg.id_to_var.size(); i++) { + all_vars.insert(cfg.id_to_var[i]); + } + for (auto node : cfg.nodes) { + for (const auto &[action, use_vars] : node->action_use_vars) { + for (auto var_id : use_vars) { + use_map[cfg.id_to_var[var_id]].insert(action); + } + actions_use_vars[action] = use_vars; + } + for (const auto &[action, def_vars] : node->action_def_vars) { + for (auto var_id : def_vars) { + def_map[cfg.id_to_var[var_id]].insert(action); + } + } + } + while (all_vars.size() > 0) { + auto v = *(all_vars.begin()); + all_vars.erase(v); + if (use_map[v].size() == 0) { + if (def_map[v].size() != 1) throw std::runtime_error("def_map[v].size()!=1"); + auto def_inst = *(def_map[v].begin()); + if (!dynamic_cast(def_inst)) { + // no side effect + def_inst->marked_as_useless = true; + const auto &use_vars = actions_use_vars[def_inst]; + for (auto var_id : use_vars) { + use_map[cfg.id_to_var[var_id]].erase(def_inst); + all_vars.insert(cfg.id_to_var[var_id]); + } + } + } + } + for (auto node : cfg.nodes) { + auto block = node->corresponding_block; + auto tmp = block->actions; + block->actions.clear(); + for (auto act : tmp) { + if (!act->marked_as_useless) { + block->actions.push_back(act); + } + } + } +} +std::shared_ptr DCE(std::shared_ptr src) { + for (auto func : src->function_defs) { + ConductDCEForFunction(func); + } + return src; +} \ No newline at end of file diff --git a/src/opt/liveanalysis.cpp b/src/opt/liveanalysis.cpp index d3af07e..508a8e1 100644 --- a/src/opt/liveanalysis.cpp +++ b/src/opt/liveanalysis.cpp @@ -22,6 +22,9 @@ void VarCollect(CFGType &cfg, std::vector &id_to_var, std::unordere }; for (auto node : cfg.nodes) { auto block = node->corresponding_block; + for (auto [_, phi_act] : block->phi_map) { + TryAddVar(phi_act->result_full); + } for (auto act : block->actions) { if (auto bin_act = std::dynamic_pointer_cast(act)) { TryAddVar(bin_act->result_full); @@ -46,6 +49,8 @@ void VarCollect(CFGType &cfg, std::vector &id_to_var, std::unordere TryAddVar(load_spilled_args_act->var_full); } else if (auto alloca_act = std::dynamic_pointer_cast(act)) { TryAddVar(alloca_act->name_full); + } else if (auto phi_act = std::dynamic_pointer_cast(act)) { + TryAddVar(phi_act->result_full); } } } @@ -63,6 +68,47 @@ void UseDefCollect(CFGType &cfg, [[maybe_unused]] std::vector &id_t std::vector cur_node_use; std::vector cur_node_def; bool use_def_init = false; + for (auto [_, phi_act] : block->phi_map) { + std::vector &cur_act_use = node->action_use_vars[phi_act.get()]; + std::vector &cur_act_def = node->action_def_vars[phi_act.get()]; + if (var_to_id.find(phi_act->result_full) != var_to_id.end()) { + cur_act_def.push_back(var_to_id[phi_act->result_full]); + } + std::unordered_set cur_act_use_tmp; + for (auto &[value, _] : phi_act->values) { + if (var_to_id.find(value) != var_to_id.end()) { + // cur_act_use.push_back(var_to_id[value]); + cur_act_use_tmp.insert(var_to_id[value]); + } + } + for (size_t i : cur_act_use_tmp) { + cur_act_use.push_back(i); + } + std::sort(cur_act_use.begin(), cur_act_use.end()); + std::sort(cur_act_def.begin(), cur_act_def.end()); + for (size_t i = 1; i < cur_act_use.size(); i++) { + if (cur_act_use[i] == cur_act_use[i - 1]) { + throw std::runtime_error("use variable appears twice in one action"); + } + } + for (size_t i = 1; i < cur_act_def.size(); i++) { + if (cur_act_def[i] == cur_act_def[i - 1]) { + throw std::runtime_error("def variable appears twice in one action"); + } + } + if (!use_def_init) { + use_def_init = true; + cur_node_use = cur_act_use; + cur_node_def = cur_act_def; + } else { + const auto &use_p = cur_node_use; + const auto &def_p = cur_node_def; + const auto &use_n = cur_act_use; + const auto &def_n = cur_act_def; + cur_node_use = GetCollectionsUnion(use_p, GetCollectionsDifference(use_n, def_p)); + cur_node_def = GetCollectionsUnion(def_p, def_n); + } + } for (auto act : block->actions) { std::vector &cur_act_use = node->action_use_vars[act.get()]; std::vector &cur_act_def = node->action_def_vars[act.get()]; @@ -182,6 +228,20 @@ void UseDefCollect(CFGType &cfg, [[maybe_unused]] std::vector &id_t } } else if (auto alloca_act = std::dynamic_pointer_cast(act)) { cur_act_def.push_back(var_to_id[alloca_act->name_full]); + } else if (auto phi_act = std::dynamic_pointer_cast(act)) { + if (var_to_id.find(phi_act->result_full) != var_to_id.end()) { + cur_act_def.push_back(var_to_id[phi_act->result_full]); + } + std::unordered_set cur_act_use_tmp; + for (auto &[value, _] : phi_act->values) { + if (var_to_id.find(value) != var_to_id.end()) { + // cur_act_use.push_back(var_to_id[value]); + cur_act_use_tmp.insert(var_to_id[value]); + } + } + for (size_t i : cur_act_use_tmp) { + cur_act_use.push_back(i); + } } std::sort(cur_act_use.begin(), cur_act_use.end()); std::sort(cur_act_def.begin(), cur_act_def.end());