diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h index ead6bbe1d5f64..1932bb9bd3dab 100644 --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -555,13 +555,18 @@ class MachineInstr /// will be dropped. void dropDebugNumber() { DebugInstrNum = 0; } - /// Emit an error referring to the source location of this instruction. - /// This should only be used for inline assembly that is somehow - /// impossible to compile. Other errors should have been handled much - /// earlier. - /// - /// If this method returns, the caller should try to recover from the error. - void emitError(StringRef Msg) const; + /// For inline asm, get the !srcloc metadata node if we have it, and decode + /// the loc cookie from it. + const MDNode *getLocCookieMD() const; + + /// Emit an error referring to the source location of this instruction. This + /// should only be used for inline assembly that is somehow impossible to + /// compile. Other errors should have been handled much earlier. + void emitInlineAsmError(const Twine &ErrMsg) const; + + // Emit an error in the LLVMContext referring to the source location of this + // instruction, if available. + void emitGenericError(const Twine &ErrMsg) const; /// Returns the target instruction descriptor of this MachineInstr. const MCInstrDesc &getDesc() const { return *MCID; } diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h index 0abff016b7779..4c34c39683e56 100644 --- a/llvm/include/llvm/IR/DiagnosticInfo.h +++ b/llvm/include/llvm/IR/DiagnosticInfo.h @@ -58,6 +58,8 @@ enum DiagnosticSeverity : char { /// Defines the different supported kind of a diagnostic. /// This enum should be extended with a new ID for each added concrete subclass. enum DiagnosticKind { + DK_Generic, + DK_GenericWithLoc, DK_InlineAsm, DK_ResourceLimit, DK_StackSize, @@ -134,6 +136,33 @@ class DiagnosticInfo { using DiagnosticHandlerFunction = std::function; +class DiagnosticInfoGeneric : public DiagnosticInfo { + const Twine &MsgStr; + const Instruction *Inst = nullptr; + +public: + /// \p MsgStr is the message to be reported to the frontend. + /// This class does not copy \p MsgStr, therefore the reference must be valid + /// for the whole life time of the Diagnostic. + DiagnosticInfoGeneric(const Twine &MsgStr, + DiagnosticSeverity Severity = DS_Error) + : DiagnosticInfo(DK_Generic, Severity), MsgStr(MsgStr) {} + + DiagnosticInfoGeneric(const Instruction *I, const Twine &ErrMsg, + DiagnosticSeverity Severity = DS_Warning) + : DiagnosticInfo(DK_Generic, Severity), MsgStr(ErrMsg), Inst(I) {} + + const Twine &getMsgStr() const { return MsgStr; } + const Instruction *getInstruction() const { return Inst; } + + /// \see DiagnosticInfo::print. + void print(DiagnosticPrinter &DP) const override; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_Generic; + } +}; + /// Diagnostic information for inline asm reporting. /// This is basically a message and an optional location. class DiagnosticInfoInlineAsm : public DiagnosticInfo { @@ -146,21 +175,12 @@ class DiagnosticInfoInlineAsm : public DiagnosticInfo { const Instruction *Instr = nullptr; public: - /// \p MsgStr is the message to be reported to the frontend. - /// This class does not copy \p MsgStr, therefore the reference must be valid - /// for the whole life time of the Diagnostic. - DiagnosticInfoInlineAsm(const Twine &MsgStr, - DiagnosticSeverity Severity = DS_Error) - : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr) {} - /// \p LocCookie if non-zero gives the line number for this report. /// \p MsgStr gives the message. /// This class does not copy \p MsgStr, therefore the reference must be valid /// for the whole life time of the Diagnostic. DiagnosticInfoInlineAsm(uint64_t LocCookie, const Twine &MsgStr, - DiagnosticSeverity Severity = DS_Error) - : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie), - MsgStr(MsgStr) {} + DiagnosticSeverity Severity = DS_Error); /// \p Instr gives the original instruction that triggered the diagnostic. /// \p MsgStr gives the message. @@ -354,6 +374,31 @@ class DiagnosticInfoWithLocationBase : public DiagnosticInfo { DiagnosticLocation Loc; }; +class DiagnosticInfoGenericWithLoc : public DiagnosticInfoWithLocationBase { +private: + /// Message to be reported. + const Twine &MsgStr; + +public: + /// \p MsgStr is the message to be reported to the frontend. + /// This class does not copy \p MsgStr, therefore the reference must be valid + /// for the whole life time of the Diagnostic. + DiagnosticInfoGenericWithLoc(const Twine &MsgStr, const Function &Fn, + const DiagnosticLocation &Loc, + DiagnosticSeverity Severity = DS_Error) + : DiagnosticInfoWithLocationBase(DK_GenericWithLoc, Severity, Fn, Loc), + MsgStr(MsgStr) {} + + const Twine &getMsgStr() const { return MsgStr; } + + /// \see DiagnosticInfo::print. + void print(DiagnosticPrinter &DP) const override; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_GenericWithLoc; + } +}; + /// Diagnostic information for stack size etc. reporting. /// This is basically a function and a size. class DiagnosticInfoResourceLimit : public DiagnosticInfoWithLocationBase { diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h index 6d4a59ba6b1f6..bbd125fd38cf1 100644 --- a/llvm/include/llvm/IR/LLVMContext.h +++ b/llvm/include/llvm/IR/LLVMContext.h @@ -305,7 +305,6 @@ class LLVMContext { /// be prepared to drop the erroneous construct on the floor and "not crash". /// The generated code need not be correct. The error message will be /// implicitly prefixed with "error: " and should not end with a ".". - void emitError(uint64_t LocCookie, const Twine &ErrorStr); void emitError(const Instruction *I, const Twine &ErrorStr); void emitError(const Twine &ErrorStr); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 6fe8d0e0af995..d1332de458208 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -312,10 +312,11 @@ static void EmitInlineAsmStr(const char *AsmStr, const MachineInstr *MI, } } if (Error) { - std::string msg; - raw_string_ostream Msg(msg); - Msg << "invalid operand in inline asm: '" << AsmStr << "'"; - MMI->getModule()->getContext().emitError(LocCookie, msg); + const Function &Fn = MI->getMF()->getFunction(); + DiagnosticInfoInlineAsm DI(LocCookie, + "invalid operand in inline asm: '" + + Twine(AsmStr) + "'"); + Fn.getContext().diagnose(DI); } } break; @@ -347,20 +348,11 @@ void AsmPrinter::emitInlineAsm(const MachineInstr *MI) const { // enabled, so we use emitRawComment. OutStreamer->emitRawComment(MAI->getInlineAsmStart()); - // Get the !srcloc metadata node if we have it, and decode the loc cookie from - // it. - uint64_t LocCookie = 0; - const MDNode *LocMD = nullptr; - for (const MachineOperand &MO : llvm::reverse(MI->operands())) { - if (MO.isMetadata() && (LocMD = MO.getMetadata()) && - LocMD->getNumOperands() != 0) { - if (const ConstantInt *CI = - mdconst::dyn_extract(LocMD->getOperand(0))) { - LocCookie = CI->getZExtValue(); - break; - } - } - } + const MDNode *LocMD = MI->getLocCookieMD(); + uint64_t LocCookie = + LocMD + ? mdconst::extract(LocMD->getOperand(0))->getZExtValue() + : 0; // Emit the inline asm to a temporary string so we can emit it through // EmitInlineAsm. @@ -397,20 +389,23 @@ void AsmPrinter::emitInlineAsm(const MachineInstr *MI) const { Msg += LS; Msg += TRI->getRegAsmName(RR); } + + const Function &Fn = MF->getFunction(); const char *Note = "Reserved registers on the clobber list may not be " "preserved across the asm statement, and clobbering them may " "lead to undefined behaviour."; - MMI->getModule()->getContext().diagnose(DiagnosticInfoInlineAsm( - LocCookie, Msg, DiagnosticSeverity::DS_Warning)); - MMI->getModule()->getContext().diagnose( + LLVMContext &Ctx = Fn.getContext(); + Ctx.diagnose(DiagnosticInfoInlineAsm(LocCookie, Msg, + DiagnosticSeverity::DS_Warning)); + Ctx.diagnose( DiagnosticInfoInlineAsm(LocCookie, Note, DiagnosticSeverity::DS_Note)); for (const Register RR : RestrRegs) { if (std::optional reason = TRI->explainReservedReg(*MF, RR)) { - MMI->getModule()->getContext().diagnose(DiagnosticInfoInlineAsm( - LocCookie, *reason, DiagnosticSeverity::DS_Note)); + Ctx.diagnose(DiagnosticInfoInlineAsm(LocCookie, *reason, + DiagnosticSeverity::DS_Note)); } } } diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index 941861da5c569..958efa79d7e9d 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -2219,26 +2219,36 @@ MachineInstrExpressionTrait::getHashValue(const MachineInstr* const &MI) { return hash_combine_range(HashComponents.begin(), HashComponents.end()); } -void MachineInstr::emitError(StringRef Msg) const { +const MDNode *MachineInstr::getLocCookieMD() const { // Find the source location cookie. - uint64_t LocCookie = 0; const MDNode *LocMD = nullptr; for (unsigned i = getNumOperands(); i != 0; --i) { if (getOperand(i-1).isMetadata() && (LocMD = getOperand(i-1).getMetadata()) && LocMD->getNumOperands() != 0) { - if (const ConstantInt *CI = - mdconst::dyn_extract(LocMD->getOperand(0))) { - LocCookie = CI->getZExtValue(); - break; - } + if (mdconst::hasa(LocMD->getOperand(0))) + return LocMD; } } - if (const MachineBasicBlock *MBB = getParent()) - if (const MachineFunction *MF = MBB->getParent()) - return MF->getFunction().getContext().emitError(LocCookie, Msg); - report_fatal_error(Msg); + return nullptr; +} + +void MachineInstr::emitInlineAsmError(const Twine &Msg) const { + assert(isInlineAsm()); + const MDNode *LocMD = getLocCookieMD(); + uint64_t LocCookie = + LocMD + ? mdconst::extract(LocMD->getOperand(0))->getZExtValue() + : 0; + LLVMContext &Ctx = getMF()->getFunction().getContext(); + Ctx.diagnose(DiagnosticInfoInlineAsm(LocCookie, Msg)); +} + +void MachineInstr::emitGenericError(const Twine &Msg) const { + const Function &Fn = getMF()->getFunction(); + Fn.getContext().diagnose( + DiagnosticInfoGenericWithLoc(Msg, Fn, getDebugLoc())); } MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL, diff --git a/llvm/lib/CodeGen/RegAllocBase.cpp b/llvm/lib/CodeGen/RegAllocBase.cpp index 449033d632100..e9fcff5c8ccbd 100644 --- a/llvm/lib/CodeGen/RegAllocBase.cpp +++ b/llvm/lib/CodeGen/RegAllocBase.cpp @@ -127,7 +127,8 @@ void RegAllocBase::allocatePhysRegs() { if (AllocOrder.empty()) report_fatal_error("no registers from class available to allocate"); else if (MI && MI->isInlineAsm()) { - MI->emitError("inline assembly requires more registers than available"); + MI->emitInlineAsmError( + "inline assembly requires more registers than available"); } else if (MI) { LLVMContext &Context = MI->getParent()->getParent()->getFunction().getContext(); diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 6babd5a3f1f96..cd1e6263d7a43 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -964,9 +964,10 @@ void RegAllocFastImpl::allocVirtReg(MachineInstr &MI, LiveReg &LR, // 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"); + MI.emitInlineAsmError( + "inline assembly requires more registers than available"); else - MI.emitError("ran out of registers during register allocation"); + MI.emitInlineAsmError("ran out of registers during register allocation"); LR.Error = true; LR.PhysReg = 0; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 519e828cc35bc..c0537c72fac4a 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -319,13 +319,14 @@ getCopyFromParts(SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, static void diagnosePossiblyInvalidConstraint(LLVMContext &Ctx, const Value *V, const Twine &ErrMsg) { const Instruction *I = dyn_cast_or_null(V); - if (!V) + if (!I) return Ctx.emitError(ErrMsg); - const char *AsmError = ", possible invalid constraint for vector type"; if (const CallInst *CI = dyn_cast(I)) - if (CI->isInlineAsm()) - return Ctx.emitError(I, ErrMsg + AsmError); + if (CI->isInlineAsm()) { + return Ctx.diagnose(DiagnosticInfoInlineAsm( + *CI, ErrMsg + ", possible invalid constraint for vector type")); + } return Ctx.emitError(I, ErrMsg); } @@ -10509,7 +10510,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call, void SelectionDAGBuilder::emitInlineAsmError(const CallBase &Call, const Twine &Message) { LLVMContext &Ctx = *DAG.getContext(); - Ctx.emitError(&Call, Message); + Ctx.diagnose(DiagnosticInfoInlineAsm(Call, Message)); // Make sure we leave the DAG in a valid state const TargetLowering &TLI = DAG.getTargetLoweringInfo(); diff --git a/llvm/lib/CodeGen/XRayInstrumentation.cpp b/llvm/lib/CodeGen/XRayInstrumentation.cpp index 8af16fa6249f4..06a85fb61b310 100644 --- a/llvm/lib/CodeGen/XRayInstrumentation.cpp +++ b/llvm/lib/CodeGen/XRayInstrumentation.cpp @@ -24,6 +24,7 @@ #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/Attributes.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Function.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" @@ -211,8 +212,12 @@ bool XRayInstrumentation::runOnMachineFunction(MachineFunction &MF) { auto &FirstMI = *FirstMBB.begin(); if (!MF.getSubtarget().isXRaySupported()) { - FirstMI.emitError("An attempt to perform XRay instrumentation for an" - " unsupported target."); + + const Function &Fn = FirstMBB.getParent()->getFunction(); + Fn.getContext().diagnose(DiagnosticInfoUnsupported( + Fn, "An attempt to perform XRay instrumentation for an" + " unsupported target.")); + return false; } diff --git a/llvm/lib/IR/DiagnosticInfo.cpp b/llvm/lib/IR/DiagnosticInfo.cpp index 234280754d547..eb91f49a524ac 100644 --- a/llvm/lib/IR/DiagnosticInfo.cpp +++ b/llvm/lib/IR/DiagnosticInfo.cpp @@ -48,6 +48,20 @@ int llvm::getNextAvailablePluginDiagnosticKind() { const char *OptimizationRemarkAnalysis::AlwaysPrint = ""; +void DiagnosticInfoGeneric::print(DiagnosticPrinter &DP) const { + DP << getMsgStr(); +} + +void DiagnosticInfoGenericWithLoc::print(DiagnosticPrinter &DP) const { + DP << getLocationStr() << ": " << getMsgStr(); +} + +DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(uint64_t LocCookie, + const Twine &MsgStr, + DiagnosticSeverity Severity) + : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie), + MsgStr(MsgStr) {} + DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr, DiagnosticSeverity Severity) diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp index e078527b597b4..eb51a751bfa08 100644 --- a/llvm/lib/IR/LLVMContext.cpp +++ b/llvm/lib/IR/LLVMContext.cpp @@ -219,12 +219,12 @@ void LLVMContext::yield() { } void LLVMContext::emitError(const Twine &ErrorStr) { - diagnose(DiagnosticInfoInlineAsm(ErrorStr)); + diagnose(DiagnosticInfoGeneric(ErrorStr)); } void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) { - assert (I && "Invalid instruction"); - diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr)); + assert(I && "Invalid instruction"); + diagnose(DiagnosticInfoGeneric(I, ErrorStr)); } static bool isDiagnosticEnabled(const DiagnosticInfo &DI) { @@ -283,10 +283,6 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) { exit(1); } -void LLVMContext::emitError(uint64_t LocCookie, const Twine &ErrorStr) { - diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr)); -} - //===----------------------------------------------------------------------===// // Metadata Kind Uniquing //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp index 049f4af4dd2f9..296c32fa4e0d0 100644 --- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp @@ -45,6 +45,12 @@ std::array, 9> SIRegisterInfo::SubRegFromChannelTable; static const std::array SubRegFromChannelTableWidthMap = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 9}; +static void emitUnsupportedError(const Function &Fn, const MachineInstr &MI, + const Twine &ErrMsg) { + Fn.getContext().diagnose( + DiagnosticInfoUnsupported(Fn, ErrMsg, MI.getDebugLoc())); +} + namespace llvm { // A temporary struct to spill SGPRs. @@ -219,7 +225,8 @@ struct SGPRSpillBuilder { // and restore. FIXME: We probably would need to reserve a register for // this. if (RS->isRegUsed(AMDGPU::SCC)) - MI->emitError("unhandled SGPR spill to memory"); + emitUnsupportedError(MF.getFunction(), *MI, + "unhandled SGPR spill to memory"); // Spill active lanes if (TmpVGPRLive) @@ -294,7 +301,8 @@ struct SGPRSpillBuilder { // and restore. FIXME: We probably would need to reserve a register for // this. if (RS->isRegUsed(AMDGPU::SCC)) - MI->emitError("unhandled SGPR spill to memory"); + emitUnsupportedError(MF.getFunction(), *MI, + "unhandled SGPR spill to memory"); // Spill active lanes TRI.buildVGPRSpillLoadStore(*this, Index, Offset, IsLoad, diff --git a/llvm/lib/Target/ARM/ARMMCInstLower.cpp b/llvm/lib/Target/ARM/ARMMCInstLower.cpp index c6d4aa9ba835c..98a95f1aa2eb5 100644 --- a/llvm/lib/Target/ARM/ARMMCInstLower.cpp +++ b/llvm/lib/Target/ARM/ARMMCInstLower.cpp @@ -183,11 +183,15 @@ void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, void ARMAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) { - if (MI.getParent()->getParent()->getInfo() - ->isThumbFunction()) - { - MI.emitError("An attempt to perform XRay instrumentation for a" - " Thumb function (not supported). Detected when emitting a sled."); + const MachineFunction *MF = MI.getParent()->getParent(); + if (MF->getInfo()->isThumbFunction()) { + const Function &Fn = MF->getFunction(); + DiagnosticInfoUnsupported Unsupported( + Fn, + "An attempt to perform XRay instrumentation for a" + " Thumb function (not supported). Detected when emitting a sled.", + MI.getDebugLoc()); + Fn.getContext().diagnose(Unsupported); return; } static const int8_t NoopsInSledCount = 6; diff --git a/llvm/lib/Target/X86/X86FloatingPoint.cpp b/llvm/lib/Target/X86/X86FloatingPoint.cpp index 34d8b774a186a..24129de9b7171 100644 --- a/llvm/lib/Target/X86/X86FloatingPoint.cpp +++ b/llvm/lib/Target/X86/X86FloatingPoint.cpp @@ -1652,24 +1652,25 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &Inst) { } if (STUses && !isMask_32(STUses)) - MI.emitError("fixed input regs must be last on the x87 stack"); + MI.emitGenericError("fixed input regs must be last on the x87 stack"); unsigned NumSTUses = llvm::countr_one(STUses); // Defs must be contiguous from the stack top. ST0-STn. if (STDefs && !isMask_32(STDefs)) { - MI.emitError("output regs must be last on the x87 stack"); + MI.emitGenericError("output regs must be last on the x87 stack"); STDefs = NextPowerOf2(STDefs) - 1; } unsigned NumSTDefs = llvm::countr_one(STDefs); // So must the clobbered stack slots. ST0-STm, m >= n. if (STClobbers && !isMask_32(STDefs | STClobbers)) - MI.emitError("clobbers must be last on the x87 stack"); + MI.emitGenericError("clobbers must be last on the x87 stack"); // Popped inputs are the ones that are also clobbered or defined. unsigned STPopped = STUses & (STDefs | STClobbers); if (STPopped && !isMask_32(STPopped)) - MI.emitError("implicitly popped regs must be last on the x87 stack"); + MI.emitGenericError( + "implicitly popped regs must be last on the x87 stack"); unsigned NumSTPopped = llvm::countr_one(STPopped); LLVM_DEBUG(dbgs() << "Asm uses " << NumSTUses << " fixed regs, pops " diff --git a/llvm/test/CodeGen/AMDGPU/sgpr-spill-to-vmem-scc-clobber-unhandled.mir b/llvm/test/CodeGen/AMDGPU/sgpr-spill-to-vmem-scc-clobber-unhandled.mir index 1957b524fa4fe..d7155f8b40f5f 100644 --- a/llvm/test/CodeGen/AMDGPU/sgpr-spill-to-vmem-scc-clobber-unhandled.mir +++ b/llvm/test/CodeGen/AMDGPU/sgpr-spill-to-vmem-scc-clobber-unhandled.mir @@ -5,8 +5,8 @@ # it. The save exec path clobbers SCC, so we currently don't have a # path which satisfies both these constraints. -# CHECK: error: unhandled SGPR spill to memory -# CHECK: error: unhandled SGPR spill to memory +# CHECK: error: :0:0: in function sgpr32_save_clobber_scc_no_sgprs void (): unhandled SGPR spill to memory +# CHECK: error: :0:0: in function sgpr32_save_clobber_scc_no_sgprs void (): unhandled SGPR spill to memory # CHECK: *** Bad machine code: Using an undefined physical register *** # CHECK: - instruction: S_CBRANCH_SCC1 %bb.2, implicit $scc # CHECK-NEXT: - operand 1: implicit $scc