-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathReachingDefinitions.cpp
More file actions
172 lines (126 loc) · 4.57 KB
/
ReachingDefinitions.cpp
File metadata and controls
172 lines (126 loc) · 4.57 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include "DataFlowAnalysis.h"
#include <iostream>
namespace DFA {
ReachingDefinitions::ReachingDefinitions(BasicBlock_list_sptr bbs) : _bbs(bbs) {
auto counter = 1;
// Compute Def[t], where t is a 'variable' name and Def[*] is a list of all
// instructions that define 't'.
for (auto& bb : *_bbs) {
for (auto& ins : bb->instructions()) {
auto instr = ins.shared_from_this();
if ( IR::isADefinition(instr) ) {
auto tgt = *instr->defs()->begin();
if (_defs.find(tgt) == _defs.end())
_defs[tgt] = make_shared<Instruction_set>();
this->_defs[tgt]->insert(instr);
}
}
}
// Compute the Kill[i] and Gen[i] sets, where 'i' is an instruction
// and Kill[*] is the set of all instruction/definitions that are killed by
// the current instruction and Gen[i] is the set of instruction/definitions
// generated by the current instruction.
for (auto& bb : *_bbs) {
_inBb[bb] = make_shared<Instruction_set>();
_outBb[bb] = make_shared<Instruction_set>();
for (auto& ins : bb->instructions()) {
auto instr = ins.shared_from_this();
_identifier[instr] = counter++;
if ( IR::isADefinition(instr) ) {
_gen[instr] = make_shared<Instruction_set>();
_gen[instr]->insert(instr);
_kill[instr] = make_shared<Instruction_set>();
auto df = _defs[ *instr->defs()->begin() ];
std::set_difference(df->begin(), df->end(),
_gen[instr]->begin(), _gen[instr]->end(),
std::inserter(*_kill[instr], _kill[instr]->begin()));
}
else {
_gen[instr] = make_shared<Instruction_set>();
_kill[instr] = make_shared<Instruction_set>();
}
_inInstr[instr] = make_shared<Instruction_set>();
_outInstr[instr] = _gen[instr];
}
}
}
// Execute reaching definitions. Up to this point In and Out of basic blocks are empty.
// Kill and Gen of each instruction is already computed.
void ReachingDefinitions::execute() {
bool hadChanges = true;
while (hadChanges) {
hadChanges = false;
for (auto& bb : *_bbs) {
// This represents the UNION of OUT of previous BBs/Instructions
auto prevOut = make_shared<Instruction_set>();
// for each predecessor basic block
auto preds = *bb->preds();
for (auto pred : preds) {
auto lastOut = _outBb[pred];
// This is just to contain tmp Unions
auto tmpRes = make_shared<Instruction_set>();
// Add together the OUT of the last bb with the OUT of the current one
std::set_union( prevOut->begin(), prevOut->end(),
lastOut->begin(), lastOut->end(),
std::inserter(*tmpRes, tmpRes->begin()));
prevOut = tmpRes;
}
// Input of current basic block
_inBb[bb] = prevOut;
// So the in of the first instruction is the UNION of the OUT of
// the predecessors. In the case of the first instruction of the BB the OUT
// is the UNION of OUT's of all predecessors.
// Now compute the IN/OUT of each instruction
for (auto& ins : bb->instructions()) {
auto instr = ins.shared_from_this();
_inInstr[instr] = prevOut;
auto tmpOut = make_shared<Instruction_set>();
// Add together the OUT of the last bb with the OUT of the current one
std::set_difference(_inInstr[instr]->begin(), _inInstr[instr]->end(),
_kill[instr]->begin(), _kill[instr]->end(),
std::inserter(*tmpOut, tmpOut->begin()));
auto newOut = make_shared<Instruction_set>();
std::set_union(_gen[instr]->begin(), _gen[instr]->end(),
tmpOut->begin(), tmpOut->end(),
std::inserter(*newOut, newOut->begin()));
if (*_outInstr[instr] != *newOut) {
hadChanges = true;
_outInstr[instr] = newOut;
}
prevOut = newOut;
}
_outBb[bb] = prevOut;
}
}
}
void ReachingDefinitions::dump() {
stringstream output;
output << "Reaching definitions dump output: " << endl;
for (auto& bb : *_bbs) {
output << "BB" << bb->id() << ":" << endl;
for (auto& ins : bb->instructions()) {
auto instr = ins.shared_from_this();
output << std::setw(3) << _identifier[instr] << ": ";
instr->dump(output);
output << "\t|-> IN {";
for (auto in : *_inInstr[instr]) {
output << _identifier[in] << " ";
}
output << "} OUT { ";
for (auto out : *_outInstr[instr]) {
output << _identifier[out] << " ";
}
output << "} KILL { ";
for (auto out : *_kill[instr]) {
output << _identifier[out] << " ";
}
output << "} GEN { ";
for (auto out : *_gen[instr]) {
output << _identifier[out] << " ";
}
output << "} " << endl;
}
}
cout << output.str() << endl;
}
}