summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/RegAllocFast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/RegAllocFast.cpp')
-rw-r--r--llvm/lib/CodeGen/RegAllocFast.cpp92
1 files changed, 65 insertions, 27 deletions
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 6babd5a3f1f9..3863ca80bb44 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -368,6 +368,9 @@ private:
bool LookAtPhysRegUses = false);
bool useVirtReg(MachineInstr &MI, MachineOperand &MO, Register VirtReg);
+ MCPhysReg getErrorAssignment(const LiveReg &LR, MachineInstr &MI,
+ const TargetRegisterClass &RC);
+
MachineBasicBlock::iterator
getMBBBeginInsertionPoint(MachineBasicBlock &MBB,
SmallSet<Register, 2> &PrologLiveIns) const;
@@ -682,7 +685,7 @@ void RegAllocFastImpl::reloadAtBegin(MachineBasicBlock &MBB) {
getMBBBeginInsertionPoint(MBB, PrologLiveIns);
for (const LiveReg &LR : LiveVirtRegs) {
MCPhysReg PhysReg = LR.PhysReg;
- if (PhysReg == 0)
+ if (PhysReg == 0 || LR.Error)
continue;
MCRegister FirstUnit = *TRI->regunits(PhysReg).begin();
@@ -963,13 +966,8 @@ void RegAllocFastImpl::allocVirtReg(MachineInstr &MI, LiveReg &LR,
if (!BestReg) {
// Nothing we can do: Report an error and keep going with an invalid
// allocation.
- if (MI.isInlineAsm())
- MI.emitError("inline assembly requires more registers than available");
- else
- MI.emitError("ran out of registers during register allocation");
-
+ LR.PhysReg = getErrorAssignment(LR, MI, RC);
LR.Error = true;
- LR.PhysReg = 0;
return;
}
@@ -984,15 +982,23 @@ void RegAllocFastImpl::allocVirtRegUndef(MachineOperand &MO) {
if (!shouldAllocateRegister(VirtReg))
return;
- LiveRegMap::const_iterator LRI = findLiveVirtReg(VirtReg);
+ LiveRegMap::iterator LRI = findLiveVirtReg(VirtReg);
MCPhysReg PhysReg;
if (LRI != LiveVirtRegs.end() && LRI->PhysReg) {
PhysReg = LRI->PhysReg;
} else {
const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg);
ArrayRef<MCPhysReg> AllocationOrder = RegClassInfo.getOrder(&RC);
- assert(!AllocationOrder.empty() && "Allocation order must not be empty");
- PhysReg = AllocationOrder[0];
+ if (AllocationOrder.empty()) {
+ // All registers in the class were reserved.
+ //
+ // It might be OK to take any entry from the class as this is an undef
+ // use, but accepting this would give different behavior than greedy and
+ // basic.
+ PhysReg = getErrorAssignment(*LRI, *MO.getParent(), RC);
+ LRI->Error = true;
+ } else
+ PhysReg = AllocationOrder.front();
}
unsigned SubRegIdx = MO.getSubReg();
@@ -1065,17 +1071,8 @@ bool RegAllocFastImpl::defineVirtReg(MachineInstr &MI, unsigned OpNum,
}
if (LRI->PhysReg == 0) {
allocVirtReg(MI, *LRI, 0, LookAtPhysRegUses);
- // If no physical register is available for LRI, we assign one at random
- // and bail out of this function immediately.
- if (LRI->Error) {
- const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg);
- ArrayRef<MCPhysReg> AllocationOrder = RegClassInfo.getOrder(&RC);
- if (AllocationOrder.empty())
- return setPhysReg(MI, MO, MCRegister::NoRegister);
- return setPhysReg(MI, MO, *AllocationOrder.begin());
- }
} else {
- assert(!isRegUsedInInstr(LRI->PhysReg, LookAtPhysRegUses) &&
+ assert((!isRegUsedInInstr(LRI->PhysReg, LookAtPhysRegUses) || LRI->Error) &&
"TODO: preassign mismatch");
LLVM_DEBUG(dbgs() << "In def of " << printReg(VirtReg, TRI)
<< " use existing assignment to "
@@ -1158,13 +1155,6 @@ bool RegAllocFastImpl::useVirtReg(MachineInstr &MI, MachineOperand &MO,
}
}
allocVirtReg(MI, *LRI, Hint, false);
- if (LRI->Error) {
- const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg);
- ArrayRef<MCPhysReg> AllocationOrder = RegClassInfo.getOrder(&RC);
- if (AllocationOrder.empty())
- return setPhysReg(MI, MO, MCRegister::NoRegister);
- return setPhysReg(MI, MO, *AllocationOrder.begin());
- }
}
LRI->LastUse = &MI;
@@ -1176,6 +1166,54 @@ bool RegAllocFastImpl::useVirtReg(MachineInstr &MI, MachineOperand &MO,
return setPhysReg(MI, MO, LRI->PhysReg);
}
+/// Query a physical register to use as a filler in contexts where the
+/// allocation has failed. This will raise an error, but not abort the
+/// compilation.
+MCPhysReg RegAllocFastImpl::getErrorAssignment(const LiveReg &LR,
+ MachineInstr &MI,
+ const TargetRegisterClass &RC) {
+ MachineFunction &MF = *MI.getMF();
+
+ // Avoid repeating the error every time a register is used.
+ bool EmitError = !MF.getProperties().hasProperty(
+ MachineFunctionProperties::Property::FailedRegAlloc);
+ if (EmitError)
+ MF.getProperties().set(MachineFunctionProperties::Property::FailedRegAlloc);
+
+ // If the allocation order was empty, all registers in the class were
+ // probably reserved. Fall back to taking the first register in the class,
+ // even if it's reserved.
+ ArrayRef<MCPhysReg> AllocationOrder = RegClassInfo.getOrder(&RC);
+ if (AllocationOrder.empty()) {
+ const Function &Fn = MF.getFunction();
+ if (EmitError) {
+ Fn.getContext().diagnose(DiagnosticInfoRegAllocFailure(
+ "no registers from class available to allocate", Fn,
+ MI.getDebugLoc()));
+ }
+
+ ArrayRef<MCPhysReg> RawRegs = RC.getRegisters();
+ assert(!RawRegs.empty() && "register classes cannot have no registers");
+ return RawRegs.front();
+ }
+
+ if (!LR.Error && EmitError) {
+ // Nothing we can do: Report an error and keep going with an invalid
+ // allocation.
+ if (MI.isInlineAsm()) {
+ MI.emitInlineAsmError(
+ "inline assembly requires more registers than available");
+ } else {
+ const Function &Fn = MBB->getParent()->getFunction();
+ Fn.getContext().diagnose(DiagnosticInfoRegAllocFailure(
+ "ran out of registers during register allocation", Fn,
+ MI.getDebugLoc()));
+ }
+ }
+
+ return AllocationOrder.front();
+}
+
/// Changes operand OpNum in MI the refer the PhysReg, considering subregs.
/// \return true if MI's MachineOperands were re-arranged/invalidated.
bool RegAllocFastImpl::setPhysReg(MachineInstr &MI, MachineOperand &MO,