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 {
}
static cl::opt<RewriterName>
RewriterOpt("rewriter",
cl::desc("Rewriter to use: (default: local)"),
cl::Prefix,
Lang Hames
committed
clEnumVal(trivial, "trivial rewriter"),
clEnumValEnd),
cl::init(local));
VirtRegRewriter::~VirtRegRewriter() {}
Lang Hames
committed
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
/// 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;
}
};
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
// ************************************************************************ //
/// 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) {
}
/// clear - Reset the state.
void clear() {
SpillSlotsOrReMatsAvailable.clear();
PhysRegsAvailable.clear();
}
const TargetRegisterInfo *getRegInfo() const { return TRI; }
/// getSpillSlotOrReMatPhysReg - If the specified stack slot or remat is
/// available in a physical register, return that PhysReg, otherwise
/// return 0.
unsigned getSpillSlotOrReMatPhysReg(int Slot) const {
std::map<int, unsigned>::const_iterator I =
SpillSlotsOrReMatsAvailable.find(Slot);
if (I != SpillSlotsOrReMatsAvailable.end()) {
return I->second >> 1; // Remove the CanClobber bit.
}
return 0;
}
/// addAvailable - Mark that the specified stack slot / remat is available
/// in the specified physreg. If CanClobber is true, the physreg can be
/// modified at any time without changing the semantics of the program.
void addAvailable(int SlotOrReMat, unsigned Reg, bool CanClobber = true) {
// If this stack slot is thought to be available in some other physreg,
// remove its record.
ModifyStackSlotOrReMat(SlotOrReMat);
PhysRegsAvailable.insert(std::make_pair(Reg, SlotOrReMat));
SpillSlotsOrReMatsAvailable[SlotOrReMat]= (Reg << 1) |
(unsigned)CanClobber;
if (SlotOrReMat > VirtRegMap::MAX_STACK_SLOT)
DOUT << "Remembering RM#" << SlotOrReMat-VirtRegMap::MAX_STACK_SLOT-1;
else
DOUT << "Remembering SS#" << SlotOrReMat;
DOUT << " in physreg " << TRI->getName(Reg) << "\n";
}
/// canClobberPhysRegForSS - Return true if the spiller is allowed to change
/// the value of the specified stackslot register if it desires. The
/// specified stack slot must be available in a physreg for this query to
/// make sense.
bool canClobberPhysRegForSS(int SlotOrReMat) const {
assert(SpillSlotsOrReMatsAvailable.count(SlotOrReMat) &&
"Value not available!");
return SpillSlotsOrReMatsAvailable.find(SlotOrReMat)->second & 1;
}
/// canClobberPhysReg - Return true if the spiller is allowed to clobber the
/// physical register where values for some stack slot(s) might be
/// available.
bool canClobberPhysReg(unsigned PhysReg) const {
std::multimap<unsigned, int>::const_iterator I =
PhysRegsAvailable.lower_bound(PhysReg);
while (I != PhysRegsAvailable.end() && I->first == PhysReg) {
int SlotOrReMat = I->second;
I++;
if (!canClobberPhysRegForSS(SlotOrReMat))
return false;
}
return true;
}
/// disallowClobberPhysReg - Unset the CanClobber bit of the specified
/// stackslot register. The register is still available but is no longer
/// allowed to be modifed.
void disallowClobberPhysReg(unsigned PhysReg);
/// ClobberPhysReg - This is called when the specified physreg changes
/// value. We use this to invalidate any info about stuff that lives in
/// it and any of its aliases.
void ClobberPhysReg(unsigned PhysReg);
/// ModifyStackSlotOrReMat - This method is called when the value in a stack
/// slot changes. This removes information about which register the
/// previous value for this slot lives in (as the previous value is dead
Loading
Loading full blame...