aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2011-05-06 21:58:30 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2011-05-06 21:58:30 +0000
commitbf4e10f2f69db24c107cb61d6fe10ed5b2047374 (patch)
treeec536f35f5ea9a02bff00d6b9dfb56fa3c85c339
parent9b668535a8900a0a86dfa410e2ed843db4b5555e (diff)
downloadexternal_llvm-bf4e10f2f69db24c107cb61d6fe10ed5b2047374.zip
external_llvm-bf4e10f2f69db24c107cb61d6fe10ed5b2047374.tar.gz
external_llvm-bf4e10f2f69db24c107cb61d6fe10ed5b2047374.tar.bz2
Emit a proper error message when register allocators run out of registers.
This can't be just an assertion, users can always write impossible inline assembly. Such an assembly statement should be included in the error message. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131024 91177308-0d34-0410-b5e6-96231b3b80d8
-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 d92d80f..32cb622 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 053344f..e9920b8 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 0000000..29c5ae5
--- /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
+}