forked from OSchip/llvm-project
[PBQP Regalloc] Pre-spill vregs that have no legal physregs.
The PBQP::RegAlloc::MatrixMetadata class assumes that matrices have at least two rows/columns (for the spill option plus at least one physreg). This patch ensures that that invariant is met by pre-spilling vregs that have no physreg options so that no node (and no corresponding edges) need be added to the PBQP graph. This fixes a bug in an out-of-tree target that was identified by Jonas Paulsson. Thanks for tracking this down Jonas! llvm-svn: 227942
This commit is contained in:
parent
c7f8bfc5e5
commit
d48bf3f912
|
@ -309,6 +309,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleAddNode(NodeId NId) {
|
void handleAddNode(NodeId NId) {
|
||||||
|
assert(G.getNodeCosts(NId).getLength() > 1 &&
|
||||||
|
"PBQP Graph should not contain single or zero-option nodes");
|
||||||
G.getNodeMetadata(NId).setup(G.getNodeCosts(NId));
|
G.getNodeMetadata(NId).setup(G.getNodeCosts(NId));
|
||||||
}
|
}
|
||||||
void handleRemoveNode(NodeId NId) {}
|
void handleRemoveNode(NodeId NId) {}
|
||||||
|
|
|
@ -126,7 +126,12 @@ private:
|
||||||
void findVRegIntervalsToAlloc(const MachineFunction &MF, LiveIntervals &LIS);
|
void findVRegIntervalsToAlloc(const MachineFunction &MF, LiveIntervals &LIS);
|
||||||
|
|
||||||
/// \brief Constructs an initial graph.
|
/// \brief Constructs an initial graph.
|
||||||
void initializeGraph(PBQPRAGraph &G);
|
void initializeGraph(PBQPRAGraph &G, VirtRegMap &VRM, Spiller &VRegSpiller);
|
||||||
|
|
||||||
|
/// \brief Spill the given VReg.
|
||||||
|
void spillVReg(unsigned VReg, SmallVectorImpl<unsigned> &NewIntervals,
|
||||||
|
MachineFunction &MF, LiveIntervals &LIS, VirtRegMap &VRM,
|
||||||
|
Spiller &VRegSpiller);
|
||||||
|
|
||||||
/// \brief Given a solved PBQP problem maps this solution back to a register
|
/// \brief Given a solved PBQP problem maps this solution back to a register
|
||||||
/// assignment.
|
/// assignment.
|
||||||
|
@ -486,7 +491,8 @@ static bool isACalleeSavedRegister(unsigned reg, const TargetRegisterInfo &TRI,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegAllocPBQP::initializeGraph(PBQPRAGraph &G) {
|
void RegAllocPBQP::initializeGraph(PBQPRAGraph &G, VirtRegMap &VRM,
|
||||||
|
Spiller &VRegSpiller) {
|
||||||
MachineFunction &MF = G.getMetadata().MF;
|
MachineFunction &MF = G.getMetadata().MF;
|
||||||
|
|
||||||
LiveIntervals &LIS = G.getMetadata().LIS;
|
LiveIntervals &LIS = G.getMetadata().LIS;
|
||||||
|
@ -494,7 +500,12 @@ void RegAllocPBQP::initializeGraph(PBQPRAGraph &G) {
|
||||||
const TargetRegisterInfo &TRI =
|
const TargetRegisterInfo &TRI =
|
||||||
*G.getMetadata().MF.getSubtarget().getRegisterInfo();
|
*G.getMetadata().MF.getSubtarget().getRegisterInfo();
|
||||||
|
|
||||||
for (auto VReg : VRegsToAlloc) {
|
std::vector<unsigned> Worklist(VRegsToAlloc.begin(), VRegsToAlloc.end());
|
||||||
|
|
||||||
|
while (!Worklist.empty()) {
|
||||||
|
unsigned VReg = Worklist.back();
|
||||||
|
Worklist.pop_back();
|
||||||
|
|
||||||
const TargetRegisterClass *TRC = MRI.getRegClass(VReg);
|
const TargetRegisterClass *TRC = MRI.getRegClass(VReg);
|
||||||
LiveInterval &VRegLI = LIS.getInterval(VReg);
|
LiveInterval &VRegLI = LIS.getInterval(VReg);
|
||||||
|
|
||||||
|
@ -529,6 +540,16 @@ void RegAllocPBQP::initializeGraph(PBQPRAGraph &G) {
|
||||||
VRegAllowed.push_back(PReg);
|
VRegAllowed.push_back(PReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for vregs that have no allowed registers. These should be
|
||||||
|
// pre-spilled and the new vregs added to the worklist.
|
||||||
|
if (VRegAllowed.empty()) {
|
||||||
|
SmallVector<unsigned, 8> NewVRegs;
|
||||||
|
spillVReg(VReg, NewVRegs, MF, LIS, VRM, VRegSpiller);
|
||||||
|
for (auto NewVReg : NewVRegs)
|
||||||
|
Worklist.push_back(NewVReg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
PBQPRAGraph::RawVector NodeCosts(VRegAllowed.size() + 1, 0);
|
PBQPRAGraph::RawVector NodeCosts(VRegAllowed.size() + 1, 0);
|
||||||
|
|
||||||
// Tweak cost of callee saved registers, as using then force spilling and
|
// Tweak cost of callee saved registers, as using then force spilling and
|
||||||
|
@ -545,6 +566,33 @@ void RegAllocPBQP::initializeGraph(PBQPRAGraph &G) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegAllocPBQP::spillVReg(unsigned VReg,
|
||||||
|
SmallVectorImpl<unsigned> &NewIntervals,
|
||||||
|
MachineFunction &MF, LiveIntervals &LIS,
|
||||||
|
VirtRegMap &VRM, Spiller &VRegSpiller) {
|
||||||
|
|
||||||
|
VRegsToAlloc.erase(VReg);
|
||||||
|
LiveRangeEdit LRE(&LIS.getInterval(VReg), NewIntervals, MF, LIS, &VRM);
|
||||||
|
VRegSpiller.spill(LRE);
|
||||||
|
|
||||||
|
const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
|
||||||
|
(void)TRI;
|
||||||
|
DEBUG(dbgs() << "VREG " << PrintReg(VReg, &TRI) << " -> SPILLED (Cost: "
|
||||||
|
<< LRE.getParent().weight << ", New vregs: ");
|
||||||
|
|
||||||
|
// Copy any newly inserted live intervals into the list of regs to
|
||||||
|
// allocate.
|
||||||
|
for (LiveRangeEdit::iterator I = LRE.begin(), E = LRE.end();
|
||||||
|
I != E; ++I) {
|
||||||
|
const LiveInterval &LI = LIS.getInterval(*I);
|
||||||
|
assert(!LI.empty() && "Empty spill range.");
|
||||||
|
DEBUG(dbgs() << PrintReg(LI.reg, &TRI) << " ");
|
||||||
|
VRegsToAlloc.insert(LI.reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(dbgs() << ")\n");
|
||||||
|
}
|
||||||
|
|
||||||
bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAGraph &G,
|
bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAGraph &G,
|
||||||
const PBQP::Solution &Solution,
|
const PBQP::Solution &Solution,
|
||||||
VirtRegMap &VRM,
|
VirtRegMap &VRM,
|
||||||
|
@ -573,28 +621,11 @@ bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAGraph &G,
|
||||||
assert(PReg != 0 && "Invalid preg selected.");
|
assert(PReg != 0 && "Invalid preg selected.");
|
||||||
VRM.assignVirt2Phys(VReg, PReg);
|
VRM.assignVirt2Phys(VReg, PReg);
|
||||||
} else {
|
} else {
|
||||||
VRegsToAlloc.erase(VReg);
|
// Spill VReg. If this introduces new intervals we'll need another round
|
||||||
SmallVector<unsigned, 8> NewSpills;
|
// of allocation.
|
||||||
LiveRangeEdit LRE(&LIS.getInterval(VReg), NewSpills, MF, LIS, &VRM);
|
SmallVector<unsigned, 8> NewVRegs;
|
||||||
VRegSpiller.spill(LRE);
|
spillVReg(VReg, NewVRegs, MF, LIS, VRM, VRegSpiller);
|
||||||
|
AnotherRoundNeeded |= !NewVRegs.empty();
|
||||||
DEBUG(dbgs() << "VREG " << PrintReg(VReg, &TRI) << " -> SPILLED (Cost: "
|
|
||||||
<< LRE.getParent().weight << ", New vregs: ");
|
|
||||||
|
|
||||||
// Copy any newly inserted live intervals into the list of regs to
|
|
||||||
// allocate.
|
|
||||||
for (LiveRangeEdit::iterator I = LRE.begin(), E = LRE.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
LiveInterval &LI = LIS.getInterval(*I);
|
|
||||||
assert(!LI.empty() && "Empty spill range.");
|
|
||||||
DEBUG(dbgs() << PrintReg(LI.reg, &TRI) << " ");
|
|
||||||
VRegsToAlloc.insert(LI.reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(dbgs() << ")\n");
|
|
||||||
|
|
||||||
// We need another round if spill intervals were added.
|
|
||||||
AnotherRoundNeeded |= !LRE.empty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,7 +714,7 @@ bool RegAllocPBQP::runOnMachineFunction(MachineFunction &MF) {
|
||||||
DEBUG(dbgs() << " PBQP Regalloc round " << Round << ":\n");
|
DEBUG(dbgs() << " PBQP Regalloc round " << Round << ":\n");
|
||||||
|
|
||||||
PBQPRAGraph G(PBQPRAGraph::GraphMetadata(MF, LIS, MBFI));
|
PBQPRAGraph G(PBQPRAGraph::GraphMetadata(MF, LIS, MBFI));
|
||||||
initializeGraph(G);
|
initializeGraph(G, VRM, *VRegSpiller);
|
||||||
ConstraintsRoot->apply(G);
|
ConstraintsRoot->apply(G);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
Loading…
Reference in New Issue