-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathregister_allocator.cpp
More file actions
95 lines (80 loc) · 2.97 KB
/
register_allocator.cpp
File metadata and controls
95 lines (80 loc) · 2.97 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
#include "register_allocator.h"
#include <algorithm>
void LinearScanRegisterAllocator::allocateRegisters(Function& func) {
// Initialize registers
registers.clear();
valueToRegister.clear();
freeRegisters.clear();
// Create physical registers
for (int i = 0; i < 16; i++) { // Assuming 16 general purpose registers
registers.emplace_back(Register{i});
freeRegisters.insert(®isters.back());
}
// Collect live intervals
std::vector<std::pair<Value*, std::pair<int, int>>> liveIntervals;
int currentPos = 0;
for (auto& block : func.blocks) {
for (auto& inst : block->instructions) {
// Record uses
for (Value* operand : inst->getOperands()) {
auto it = valueToRegister.find(operand);
if (it == valueToRegister.end()) {
liveIntervals.emplace_back(operand, std::make_pair(currentPos, currentPos));
}
}
// Record definitions
for (Value* result : inst->getResults()) {
liveIntervals.emplace_back(result, std::make_pair(currentPos, currentPos));
}
currentPos++;
}
}
// Sort intervals by start position
std::sort(liveIntervals.begin(), liveIntervals.end(),
[](const auto& a, const auto& b) {
return a.second.first < b.second.first;
});
// Allocate registers using linear scan
for (auto& interval : liveIntervals) {
Value* value = interval.first;
// Free expired intervals
for (auto it = valueToRegister.begin(); it != valueToRegister.end();) {
if (it->second && it->second->isExpired(interval.second.first)) {
freeRegister(it->second);
it = valueToRegister.erase(it);
} else {
++it;
}
}
// Allocate register
Register* reg = getRegister(value);
if (reg) {
valueToRegister[value] = reg;
reg->setLiveInterval(interval.second.first, interval.second.second);
}
}
}
Register* LinearScanRegisterAllocator::getRegister(Value* value) {
// First try to find a free register
if (!freeRegisters.empty()) {
Register* reg = *freeRegisters.begin();
freeRegisters.erase(freeRegisters.begin());
return reg;
}
// If no free registers, implement spilling
// This is a simple implementation - in practice, you'd want more sophisticated spilling heuristics
Register* spilledReg = nullptr;
int latestEnd = -1;
for (auto& [val, reg] : valueToRegister) {
if (reg && reg->getEndPos() > latestEnd) {
latestEnd = reg->getEndPos();
spilledReg = reg;
}
}
return spilledReg;
}
void LinearScanRegisterAllocator::freeRegister(Register* reg) {
if (reg) {
freeRegisters.insert(reg);
}
}