-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathl3_dce.cpp
96 lines (82 loc) · 3.08 KB
/
l3_dce.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "cfg/cfg.h"
#include <iostream>
#include <unordered_set>
#include <unordered_map>
#include <nlohmann/json.hpp>
void DeadCodeElimination(BasicBlocks &blocks, bool simple_mode);
void DeleteUnusedCode(BasicBlocks &blocks, bool simple_mode);
void DeleteReAssigned(BasicBlocks &blocks);
int main(int argc, char** argv){
json j;
j = j.parse(std::cin);
//perform dead code elimination, and output modified code
bool simple_mode = (argc > 1);
json outputFuncs = json::array();
for(const auto &func: j["functions"]){
BasicBlocks blocks(func);
DeadCodeElimination(blocks, simple_mode);
outputFuncs.push_back(std::move(blocks.Dump()));
}
std::cout << json{{"functions", outputFuncs}} << std::endl;
return 0;
}
void DeadCodeElimination(BasicBlocks &blocks, bool simple_mode){
DeleteUnusedCode(blocks, simple_mode);
DeleteReAssigned(blocks);
}
void DeleteUnusedCode(BasicBlocks &blocks, bool simple_mode){
int changed = true;
while(changed){
//collect all usage
std::unordered_set<std::string> used;
for(const auto &block: blocks){
for(const auto &inst: block.instrs){
if(!inst.contains("args")) continue;
for(std::string operand: inst["args"]){ used.insert(operand); }
}
}
std::vector<std::vector<int>> redundent_lines(blocks.size());
for(int i = 0; i < blocks.size(); i++){
auto &instrs = blocks[i].instrs;
for(int j = 0; j < instrs.size(); j++){
if(!instrs[j].contains("dest")) continue;
if(used.count(instrs[j]["dest"]) == 0){
redundent_lines[i].push_back(j);
}
}
}
changed = false;
for(int i = 0; i < redundent_lines.size(); i++){
auto &instrs = blocks[i].instrs;
auto &lines = redundent_lines[i];
for(auto riter = lines.rbegin(); riter != lines.rend(); riter++){
instrs.erase(instrs.begin() + *riter);
if(!simple_mode)changed = true;
}
}
}
}
void DeleteReAssigned(BasicBlocks &blocks){
for(Block& block: blocks){
std::unordered_map<std::string, int> unused_var;
std::vector<int> redundent_lines;
auto &instrs = block.instrs;
for(int i = 0; i < instrs.size(); i++){
auto &inst = instrs[i];
if(inst.contains("args")){
for(const auto &arg: inst["args"]){
auto iter = unused_var.find(arg);
if(iter == unused_var.end()) continue;
unused_var.erase(iter);
}
}
if(!inst.contains("dest")) continue;
auto iter = unused_var.find(inst["dest"]);
if(iter != unused_var.end()) redundent_lines.push_back(iter->second);
unused_var[inst["dest"]] = i;
}
for(auto riter = redundent_lines.rbegin(); riter != redundent_lines.rend(); riter++){
instrs.erase(instrs.begin() + *riter);
}
}
}