diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h --- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -523,6 +523,13 @@ /// markSuperRegs() and checkAllSuperRegsMarked() in this case. virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; + /// Returns either nullptr or a non null pointer to a string explaining + /// why the given register is reserved for the given machine function. + virtual const char *explainReservedReg(const MachineFunction &MF, + MCRegister PhysReg) const { + return nullptr; + } + /// Returns false if we can't guarantee that Physreg, specified as an IR asm /// clobber constraint, will be preserved across the statement. virtual bool isAsmClobberable(const MachineFunction &MF, diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -411,6 +411,13 @@ LocCookie, Msg, DiagnosticSeverity::DS_Warning)); MMI->getModule()->getContext().diagnose( DiagnosticInfoInlineAsm(LocCookie, Note, DiagnosticSeverity::DS_Note)); + + for (const Register RR: RestrRegs) { + if (const char* reason = TRI->explainReservedReg(*MF, RR)) { + MMI->getModule()->getContext().diagnose( + DiagnosticInfoInlineAsm(LocCookie, reason, DiagnosticSeverity::DS_Note)); + } + } } emitInlineAsm(OS.str(), getSubtargetInfo(), TM.Options.MCOptions, LocMD, diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h @@ -89,6 +89,8 @@ const uint32_t *getWindowsStackProbePreservedMask() const; BitVector getReservedRegs(const MachineFunction &MF) const override; + const char *explainReservedReg(const MachineFunction &MF, + MCRegister PhysReg) const override; bool isAsmClobberable(const MachineFunction &MF, MCRegister PhysReg) const override; const TargetRegisterClass * diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -308,6 +308,15 @@ return CSR_AArch64_StackProbe_Windows_RegMask; } +const char *AArch64RegisterInfo::explainReservedReg(const MachineFunction &MF, + MCRegister PhysReg) const { + if (hasBasePointer(MF) && + (PhysReg == AArch64::X19 || PhysReg == AArch64::W19)) + return "X16 is used as the frame base pointer register."; + + return nullptr; +} + BitVector AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const { const AArch64FrameLowering *TFI = getFrameLowering(MF); diff --git a/llvm/test/CodeGen/AArch64/inline-asm-clobber-base-frame-pointer.ll b/llvm/test/CodeGen/AArch64/inline-asm-clobber-base-frame-pointer.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/inline-asm-clobber-base-frame-pointer.ll @@ -0,0 +1,11 @@ +; RUN: llc <%s -mtriple=aarch64-none-eabi 2>&1 | FileCheck %s + +; CHECK: warning: inline asm clobber list contains reserved registers: X19 +; CHECK: note: X16 is used as the frame base pointer register. + +define dso_local void @alloca(i64 %size, i8* %base) { +entryz: + %a = alloca i128, i64 %size, align 64 + call void asm sideeffect "nop", "~{x19}"() + ret void +} \ No newline at end of file