From a5c889982a5d1f5695298162474de4d1e1888065 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 6 May 2011 21:58:30 +0000 Subject: [PATCH] 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. llvm-svn: 131024 --- llvm/lib/CodeGen/RegAllocBasic.cpp | 20 ++++++++++++++++++++ llvm/lib/CodeGen/RegAllocGreedy.cpp | 5 ++++- llvm/test/CodeGen/X86/inline-asm-error.ll | 17 +++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/X86/inline-asm-error.ll diff --git a/llvm/lib/CodeGen/RegAllocBasic.cpp b/llvm/lib/CodeGen/RegAllocBasic.cpp index d92d80f181fc..32cb62223b5f 100644 --- a/llvm/lib/CodeGen/RegAllocBasic.cpp +++ b/llvm/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/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp index 053344f46e8a..e9920b827127 100644 --- a/llvm/lib/CodeGen/RegAllocGreedy.cpp +++ b/llvm/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/llvm/test/CodeGen/X86/inline-asm-error.ll b/llvm/test/CodeGen/X86/inline-asm-error.ll new file mode 100644 index 000000000000..29c5ae51cf82 --- /dev/null +++ b/llvm/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 + +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 +}