write DCE
This commit is contained in:
@ -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<class PhiItem> corresponding_phi;
|
||||
|
4
include/opt/dce.h
Normal file
4
include/opt/dce.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include "IR/IR_basic.h"
|
||||
|
||||
std::shared_ptr<ModuleItem> DCE(std::shared_ptr<ModuleItem> src);
|
@ -2,4 +2,5 @@
|
||||
#include "gen.h"
|
||||
#include "global_var_cache.h"
|
||||
#include "mem2reg.h"
|
||||
#include "regalloc.h"
|
||||
#include "regalloc.h"
|
||||
#include "dce.h"
|
@ -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);
|
||||
|
63
src/opt/dce.cpp
Normal file
63
src/opt/dce.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "dce.h"
|
||||
#include "IR/IR_basic.h"
|
||||
#include "cfg.h"
|
||||
#include "liveanalysis.h"
|
||||
void ConductDCEForFunction(std::shared_ptr<FunctionDefItem> func);
|
||||
|
||||
void ConductDCEForFunction(std::shared_ptr<FunctionDefItem> func) {
|
||||
CFGType cfg;
|
||||
cfg = BuildCFGForFunction(func);
|
||||
LiveAnalysis(cfg);
|
||||
std::unordered_set<std::string> all_vars;
|
||||
std::unordered_map<std::string, std::unordered_set<ActionItem *>> use_map, def_map;
|
||||
std::unordered_map<ActionItem *, std::vector<size_t>> 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<CallItem *>(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<ModuleItem> DCE(std::shared_ptr<ModuleItem> src) {
|
||||
for (auto func : src->function_defs) {
|
||||
ConductDCEForFunction(func);
|
||||
}
|
||||
return src;
|
||||
}
|
@ -22,6 +22,9 @@ void VarCollect(CFGType &cfg, std::vector<std::string> &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<BinaryOperationAction>(act)) {
|
||||
TryAddVar(bin_act->result_full);
|
||||
@ -46,6 +49,8 @@ void VarCollect(CFGType &cfg, std::vector<std::string> &id_to_var, std::unordere
|
||||
TryAddVar(load_spilled_args_act->var_full);
|
||||
} else if (auto alloca_act = std::dynamic_pointer_cast<AllocaAction>(act)) {
|
||||
TryAddVar(alloca_act->name_full);
|
||||
} else if (auto phi_act = std::dynamic_pointer_cast<PhiItem>(act)) {
|
||||
TryAddVar(phi_act->result_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -63,6 +68,47 @@ void UseDefCollect(CFGType &cfg, [[maybe_unused]] std::vector<std::string> &id_t
|
||||
std::vector<size_t> cur_node_use;
|
||||
std::vector<size_t> cur_node_def;
|
||||
bool use_def_init = false;
|
||||
for (auto [_, phi_act] : block->phi_map) {
|
||||
std::vector<size_t> &cur_act_use = node->action_use_vars[phi_act.get()];
|
||||
std::vector<size_t> &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<size_t> 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<size_t> &cur_act_use = node->action_use_vars[act.get()];
|
||||
std::vector<size_t> &cur_act_def = node->action_def_vars[act.get()];
|
||||
@ -182,6 +228,20 @@ void UseDefCollect(CFGType &cfg, [[maybe_unused]] std::vector<std::string> &id_t
|
||||
}
|
||||
} else if (auto alloca_act = std::dynamic_pointer_cast<AllocaAction>(act)) {
|
||||
cur_act_def.push_back(var_to_id[alloca_act->name_full]);
|
||||
} else if (auto phi_act = std::dynamic_pointer_cast<PhiItem>(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<size_t> 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());
|
||||
|
Reference in New Issue
Block a user