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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
|
//===-- llvm/CodeGen/VirtRegMap.h - Virtual Register Map -*- C++ -*--------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a virtual register map. This maps virtual registers to
// physical registers and virtual registers to stack slots. It is created and
// updated by a register allocator and then used by a machine code rewriter that
// adds spill code and rewrites virtual into physical register references.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_VIRTREGMAP_H
#define LLVM_CODEGEN_VIRTREGMAP_H
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/Support/Streams.h"
#include <map>
namespace llvm {
class MachineInstr;
class MachineFunction;
class TargetInstrInfo;
class VirtRegMap {
public:
enum {
NO_PHYS_REG = 0,
NO_STACK_SLOT = (1L << 30)-1,
MAX_STACK_SLOT = (1L << 18)-1
};
enum ModRef { isRef = 1, isMod = 2, isModRef = 3 };
typedef std::multimap<MachineInstr*,
std::pair<unsigned, ModRef> > MI2VirtMapTy;
private:
const TargetInstrInfo &TII;
MachineFunction &MF;
/// Virt2PhysMap - This is a virtual to physical register
/// mapping. Each virtual register is required to have an entry in
/// it; even spilled virtual registers (the register mapped to a
/// spilled register is the temporary used to load it from the
/// stack).
IndexedMap<unsigned, VirtReg2IndexFunctor> Virt2PhysMap;
/// Virt2StackSlotMap - This is virtual register to stack slot
/// mapping. Each spilled virtual register has an entry in it
/// which corresponds to the stack slot this register is spilled
/// at.
IndexedMap<int, VirtReg2IndexFunctor> Virt2StackSlotMap;
IndexedMap<int, VirtReg2IndexFunctor> Virt2ReMatIdMap;
/// MI2VirtMap - This is MachineInstr to virtual register
/// mapping. In the case of memory spill code being folded into
/// instructions, we need to know which virtual register was
/// read/written by this instruction.
MI2VirtMapTy MI2VirtMap;
/// ReMatMap - This is virtual register to re-materialized instruction
/// mapping. Each virtual register whose definition is going to be
/// re-materialized has an entry in it.
IndexedMap<MachineInstr*, VirtReg2IndexFunctor> ReMatMap;
/// ReMatId - Instead of assigning a stack slot to a to be rematerialized
/// virtual register, an unique id is being assigned. This keeps track of
/// the highest id used so far. Note, this starts at (1<<18) to avoid
/// conflicts with stack slot numbers.
int ReMatId;
VirtRegMap(const VirtRegMap&); // DO NOT IMPLEMENT
void operator=(const VirtRegMap&); // DO NOT IMPLEMENT
public:
explicit VirtRegMap(MachineFunction &mf);
void grow();
/// @brief returns true if the specified virtual register is
/// mapped to a physical register
bool hasPhys(unsigned virtReg) const {
return getPhys(virtReg) != NO_PHYS_REG;
}
/// @brief returns the physical register mapped to the specified
/// virtual register
unsigned getPhys(unsigned virtReg) const {
assert(MRegisterInfo::isVirtualRegister(virtReg));
return Virt2PhysMap[virtReg];
}
/// @brief creates a mapping for the specified virtual register to
/// the specified physical register
void assignVirt2Phys(unsigned virtReg, unsigned physReg) {
assert(MRegisterInfo::isVirtualRegister(virtReg) &&
MRegisterInfo::isPhysicalRegister(physReg));
assert(Virt2PhysMap[virtReg] == NO_PHYS_REG &&
"attempt to assign physical register to already mapped "
"virtual register");
Virt2PhysMap[virtReg] = physReg;
}
/// @brief clears the specified virtual register's, physical
/// register mapping
void clearVirt(unsigned virtReg) {
assert(MRegisterInfo::isVirtualRegister(virtReg));
assert(Virt2PhysMap[virtReg] != NO_PHYS_REG &&
"attempt to clear a not assigned virtual register");
Virt2PhysMap[virtReg] = NO_PHYS_REG;
}
/// @brief clears all virtual to physical register mappings
void clearAllVirt() {
Virt2PhysMap.clear();
grow();
}
/// @brief returns true is the specified virtual register is not
/// mapped to a stack slot or rematerialized.
bool isAssignedReg(unsigned virtReg) const {
return getStackSlot(virtReg) == NO_STACK_SLOT &&
getReMatId(virtReg) == NO_STACK_SLOT;
}
/// @brief returns the stack slot mapped to the specified virtual
/// register
int getStackSlot(unsigned virtReg) const {
assert(MRegisterInfo::isVirtualRegister(virtReg));
return Virt2StackSlotMap[virtReg];
}
/// @brief returns the rematerialization id mapped to the specified virtual
/// register
int getReMatId(unsigned virtReg) const {
assert(MRegisterInfo::isVirtualRegister(virtReg));
return Virt2ReMatIdMap[virtReg];
}
/// @brief create a mapping for the specifed virtual register to
/// the next available stack slot
int assignVirt2StackSlot(unsigned virtReg);
/// @brief create a mapping for the specified virtual register to
/// the specified stack slot
void assignVirt2StackSlot(unsigned virtReg, int frameIndex);
/// @brief assign an unique re-materialization id to the specified
/// virtual register.
int assignVirtReMatId(unsigned virtReg);
/// @brief assign an unique re-materialization id to the specified
/// virtual register.
void assignVirtReMatId(unsigned virtReg, int id);
/// @brief returns true if the specified virtual register is being
/// re-materialized.
bool isReMaterialized(unsigned virtReg) const {
return ReMatMap[virtReg] != NULL;
}
/// @brief returns the original machine instruction being re-issued
/// to re-materialize the specified virtual register.
MachineInstr *getReMaterializedMI(unsigned virtReg) const {
return ReMatMap[virtReg];
}
/// @brief records the specified virtual register will be
/// re-materialized and the original instruction which will be re-issed
/// for this purpose. If parameter all is true, then all uses of the
/// registers are rematerialized and it's safe to delete the definition.
void setVirtIsReMaterialized(unsigned virtReg, MachineInstr *def) {
ReMatMap[virtReg] = def;
}
/// @brief Updates information about the specified virtual register's value
/// folded into newMI machine instruction. The OpNum argument indicates the
/// operand number of OldMI that is folded.
void virtFolded(unsigned VirtReg, MachineInstr *OldMI, unsigned OpNum,
MachineInstr *NewMI);
/// @brief returns the virtual registers' values folded in memory
/// operands of this instruction
std::pair<MI2VirtMapTy::const_iterator, MI2VirtMapTy::const_iterator>
getFoldedVirts(MachineInstr* MI) const {
return MI2VirtMap.equal_range(MI);
}
/// RemoveFromFoldedVirtMap - If the specified machine instruction is in
/// the folded instruction map, remove its entry from the map.
void RemoveFromFoldedVirtMap(MachineInstr *MI) {
MI2VirtMap.erase(MI);
}
void print(std::ostream &OS) const;
void print(std::ostream *OS) const { if (OS) print(*OS); }
void dump() const;
};
inline std::ostream *operator<<(std::ostream *OS, const VirtRegMap &VRM) {
VRM.print(OS);
return OS;
}
inline std::ostream &operator<<(std::ostream &OS, const VirtRegMap &VRM) {
VRM.print(OS);
return OS;
}
/// Spiller interface: Implementations of this interface assign spilled
/// virtual registers to stack slots, rewriting the code.
struct Spiller {
virtual ~Spiller();
virtual bool runOnMachineFunction(MachineFunction &MF,
VirtRegMap &VRM) = 0;
};
/// createSpiller - Create an return a spiller object, as specified on the
/// command line.
Spiller* createSpiller();
} // End llvm namespace
#endif
|