-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathopt_consolidate.cpp
108 lines (75 loc) · 1.87 KB
/
opt_consolidate.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
97
98
99
100
101
102
103
104
105
106
#include "types.h"
#include "common.h"
#include <algorithm>
#include "Expression.h"
#include "branch.h"
/*
Before:
.1
...
LDA #0
BRA .3
.2
...
LDA #0
BRA .3
.3
...
After:
.1
...
BRA .3
.2
...
BRA .3
.3
LDA #0
...
Only possible if lines are identical in all previous blocks.
*/
bool operator==(BasicLine & a, BasicLine &b)
{
if (&a == &b) return true;
if (a.label != b.label) return false;
if (a.directive != b.directive) return false;
if (a.opcode != b.opcode) return false;
if (a.branch != b.branch) return false;
return std::equal(
std::begin(a.operands), std::end(a.operands),
std::begin(b.operands), std::end(b.operands),
[](ExpressionPtr a, ExpressionPtr b){
if (a && b) return *a == *b;
return a == b;
});
}
// common line consolidation.
bool common_line_consolidation(BasicBlockPtr block) {
// if all previous entries flow into this one (and only) this one,
// move any common trailing lines.
if (!block || block->dead || block->entry_node || block->global_node) return false;
auto &prev_set = block->prev_set;
if (prev_set.size() < 2) return false;
if (std::any_of(prev_set.begin(), prev_set.end(), [](BasicBlockPtr b){
return b->next_set.size() != 1; // also check if exit branch is null or always....
})) return false;
BasicBlockPtr first = prev_set.front();
bool delta = false;
while(!first->lines.empty()) {
bool ok;
BasicLinePtr target = first->lines.back();
ok = std::all_of(prev_set.begin(), prev_set.end(), [target](BasicBlockPtr b){
if (b->lines.empty()) return false;
BasicLinePtr l = b->lines.back();
if (l == target || *l == *target) return true;
return false;
});
if (!ok) break;
// now move it...
for (auto &b : prev_set) { b->lines.pop_back(); }
// need to reset reginfo?
block->lines.emplace_front(std::move(target));
delta = true;
block->dirty = true;
}
return delta;
}