aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/RegAllocBasic.cpp20
-rw-r--r--lib/CodeGen/RegAllocGreedy.cpp5
-rw-r--r--test/CodeGen/X86/inline-asm-error.ll17
3 files changed, 41 insertions, 1 deletions
diff --git a/lib/CodeGen/RegAllocBasic.cpp b/lib/CodeGen/RegAllocBasic.cpp
index d92d80f181..32cb62223b 100644
--- a/lib/CodeGen/RegAllocBasic.cpp
+++ b/lib/CodeGen/RegAllocBasic.cpp
@@ -321,6 +321,23 @@ void RegAllocBase::allocatePhysRegs() {
VirtRegVec SplitVRegs;
unsigned AvailablePhysReg = selectOrSplit(*VirtReg, SplitVRegs);
+ if (AvailablePhysReg == ~0u) {
+ // selectOrSplit failed to find a register!
+ std::string msg;
+ raw_string_ostream Msg(msg);
+ Msg << "Ran out of registers during register allocation!"
+ "\nCannot allocate: " << *VirtReg;
+ for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(VirtReg->reg);
+ MachineInstr *MI = I.skipInstruction();) {
+ if (!MI->isInlineAsm())
+ continue;
+ Msg << "\nPlease check your inline asm statement for "
+ "invalid constraints:\n";
+ MI->print(Msg, &VRM->getMachineFunction().getTarget());
+ }
+ report_fatal_error(Msg.str());
+ }
+
if (AvailablePhysReg)
assign(*VirtReg, AvailablePhysReg);
@@ -498,8 +515,11 @@ unsigned RABasic::selectOrSplit(LiveInterval &VirtReg,
// Tell the caller to allocate to this newly freed physical register.
return *PhysRegI;
}
+
// No other spill candidates were found, so spill the current VirtReg.
DEBUG(dbgs() << "spilling: " << VirtReg << '\n');
+ if (!VirtReg.isSpillable())
+ return ~0u;
LiveRangeEdit LRE(VirtReg, SplitVRegs);
spiller().spill(LRE);
diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp
index 053344f46e..e9920b8271 100644
--- a/lib/CodeGen/RegAllocGreedy.cpp
+++ b/lib/CodeGen/RegAllocGreedy.cpp
@@ -1380,7 +1380,10 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg,
return 0;
}
- assert(Stage < RS_Spill && "Cannot allocate after spilling");
+ // If we couldn't allocate a register from spilling, there is probably some
+ // invalid inline assembly. The base class wil report it.
+ if (Stage >= RS_Spill)
+ return ~0u;
// Try splitting VirtReg or interferences.
unsigned PhysReg = trySplit(VirtReg, Order, NewVRegs);
diff --git a/test/CodeGen/X86/inline-asm-error.ll b/test/CodeGen/X86/inline-asm-error.ll
new file mode 100644
index 0000000000..29c5ae51cf
--- /dev/null
+++ b/test/CodeGen/X86/inline-asm-error.ll
@@ -0,0 +1,17 @@
+; RUN: not llc -march x86 -regalloc=fast < %s 2> %t1
+; RUN: not llc -march x86 -regalloc=basic < %s 2> %t2
+; RUN: not llc -march x86 -regalloc=greedy < %s 2> %t3
+; RUN: FileCheck %s < %t1
+; RUN: FileCheck %s < %t2
+; RUN: FileCheck %s < %t3
+
+; The register allocator must fail on this function, and it should print the
+; inline asm in the diagnostic.
+; CHECK: LLVM ERROR: Ran out of registers during register allocation!
+; CHECK: INLINEASM <es:hello world>
+
+define void @f(i32 %x0, i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5, i32 %x6, i32 %x7, i32 %x8, i32 %x9) nounwind ssp {
+entry:
+ tail call void asm sideeffect "hello world", "r,r,r,r,r,r,r,r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %x0, i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5, i32 %x6, i32 %x7, i32 %x8, i32 %x9) nounwind
+ ret void
+}