Newer
Older
//===-- llvm/CodeGen/Rewriter.cpp - Rewriter -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "virtregrewriter"
#include "VirtRegRewriter.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
using namespace llvm;
STATISTIC(NumDSE , "Number of dead stores elided");
STATISTIC(NumDSS , "Number of dead spill slots removed");
STATISTIC(NumCommutes, "Number of instructions commuted");
STATISTIC(NumDRM , "Number of re-materializable defs elided");
STATISTIC(NumStores , "Number of stores added");
STATISTIC(NumPSpills , "Number of physical register spills");
STATISTIC(NumOmitted , "Number of reloads omited");
STATISTIC(NumAvoided , "Number of reloads deemed unnecessary");
STATISTIC(NumCopified, "Number of available reloads turned into copies");
STATISTIC(NumReMats , "Number of re-materialization");
STATISTIC(NumLoads , "Number of loads added");
STATISTIC(NumReused , "Number of values reused");
STATISTIC(NumDCE , "Number of copies elided");
STATISTIC(NumSUnfold , "Number of stores unfolded");
STATISTIC(NumModRefUnfold, "Number of modref unfolded");
namespace {
Lang Hames
committed
enum RewriterName { simple, local, trivial };
}
static cl::opt<RewriterName>
RewriterOpt("rewriter",
cl::desc("Rewriter to use: (default: local)"),
cl::Prefix,
Lang Hames
committed
cl::values(clEnumVal(simple, "simple rewriter"),
clEnumVal(local, "local rewriter"),
clEnumVal(trivial, "trivial rewriter"),
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
clEnumValEnd),
cl::init(local));
VirtRegRewriter::~VirtRegRewriter() {}
// ****************************** //
// Simple Spiller Implementation //
// ****************************** //
struct VISIBILITY_HIDDEN SimpleRewriter : public VirtRegRewriter {
bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM,
LiveIntervals* LIs) {
DOUT << "********** REWRITE MACHINE CODE **********\n";
DOUT << "********** Function: " << MF.getFunction()->getName() << '\n';
const TargetMachine &TM = MF.getTarget();
const TargetInstrInfo &TII = *TM.getInstrInfo();
const TargetRegisterInfo &TRI = *TM.getRegisterInfo();
// LoadedRegs - Keep track of which vregs are loaded, so that we only load
// each vreg once (in the case where a spilled vreg is used by multiple
// operands). This is always smaller than the number of operands to the
// current machine instr, so it should be small.
std::vector<unsigned> LoadedRegs;
for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end();
MBBI != E; ++MBBI) {
DOUT << MBBI->getBasicBlock()->getName() << ":\n";
MachineBasicBlock &MBB = *MBBI;
for (MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end();
MII != E; ++MII) {
MachineInstr &MI = *MII;
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI.getOperand(i);
if (MO.isReg() && MO.getReg()) {
if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
unsigned VirtReg = MO.getReg();
unsigned SubIdx = MO.getSubReg();
unsigned PhysReg = VRM.getPhys(VirtReg);
unsigned RReg = SubIdx ? TRI.getSubReg(PhysReg, SubIdx) : PhysReg;
if (!VRM.isAssignedReg(VirtReg)) {
int StackSlot = VRM.getStackSlot(VirtReg);
const TargetRegisterClass* RC =
MF.getRegInfo().getRegClass(VirtReg);
if (MO.isUse() &&
std::find(LoadedRegs.begin(), LoadedRegs.end(), VirtReg)
== LoadedRegs.end()) {
TII.loadRegFromStackSlot(MBB, &MI, PhysReg, StackSlot, RC);
MachineInstr *LoadMI = prior(MII);
VRM.addSpillSlotUse(StackSlot, LoadMI);
LoadedRegs.push_back(VirtReg);
++NumLoads;
DOUT << '\t' << *LoadMI;
}
if (MO.isDef()) {
TII.storeRegToStackSlot(MBB, next(MII), PhysReg, true,
StackSlot, RC);
MachineInstr *StoreMI = next(MII);
VRM.addSpillSlotUse(StackSlot, StoreMI);
++NumStores;
}
}
MF.getRegInfo().setPhysRegUsed(RReg);
MI.getOperand(i).setReg(RReg);
MI.getOperand(i).setSubReg(0);
} else {
MF.getRegInfo().setPhysRegUsed(MO.getReg());
}
}
}
DOUT << '\t' << MI;
LoadedRegs.clear();
}
}
return true;
}
};
Lang Hames
committed
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
/// This class is intended for use with the new spilling framework only. It
/// rewrites vreg def/uses to use the assigned preg, but does not insert any
/// spill code.
struct VISIBILITY_HIDDEN TrivialRewriter : public VirtRegRewriter {
bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM,
LiveIntervals* LIs) {
DOUT << "********** REWRITE MACHINE CODE **********\n";
DOUT << "********** Function: " << MF.getFunction()->getName() << '\n';
MachineRegisterInfo *mri = &MF.getRegInfo();
bool changed = false;
for (LiveIntervals::iterator liItr = LIs->begin(), liEnd = LIs->end();
liItr != liEnd; ++liItr) {
if (TargetRegisterInfo::isVirtualRegister(liItr->first)) {
if (VRM.hasPhys(liItr->first)) {
unsigned preg = VRM.getPhys(liItr->first);
mri->replaceRegWith(liItr->first, preg);
mri->setPhysRegUsed(preg);
changed = true;
}
}
else {
if (!liItr->second->empty()) {
mri->setPhysRegUsed(liItr->first);
}
}
}
return changed;
}
};
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
// ************************************************************************ //
/// AvailableSpills - As the local rewriter is scanning and rewriting an MBB
/// from top down, keep track of which spill slots or remat are available in
/// each register.
///
/// Note that not all physregs are created equal here. In particular, some
/// physregs are reloads that we are allowed to clobber or ignore at any time.
/// Other physregs are values that the register allocated program is using
/// that we cannot CHANGE, but we can read if we like. We keep track of this
/// on a per-stack-slot / remat id basis as the low bit in the value of the
/// SpillSlotsAvailable entries. The predicate 'canClobberPhysReg()' checks
/// this bit and addAvailable sets it if.
class VISIBILITY_HIDDEN AvailableSpills {
const TargetRegisterInfo *TRI;
const TargetInstrInfo *TII;
// SpillSlotsOrReMatsAvailable - This map keeps track of all of the spilled
// or remat'ed virtual register values that are still available, due to
// being loaded or stored to, but not invalidated yet.
std::map<int, unsigned> SpillSlotsOrReMatsAvailable;
// PhysRegsAvailable - This is the inverse of SpillSlotsOrReMatsAvailable,
// indicating which stack slot values are currently held by a physreg. This
// is used to invalidate entries in SpillSlotsOrReMatsAvailable when a
// physreg is modified.
std::multimap<unsigned, int> PhysRegsAvailable;
void disallowClobberPhysRegOnly(unsigned PhysReg);
void ClobberPhysRegOnly(unsigned PhysReg);
public:
AvailableSpills(const TargetRegisterInfo *tri, const TargetInstrInfo *tii)
: TRI(tri), TII(tii) {
}
Loading
Loading full blame...