diff --git a/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp b/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp --- a/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp +++ b/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp @@ -80,6 +80,13 @@ } static bool runOnFunction(Function &F, bool PostInlining) { + // The asm in a naked function may reasonably expect the argument registers + // and the return address register (if present) to be live. An inserted + // function call will clobber these registers. Simply skip naked functions for + // all targets. + if (F.hasFnAttribute(Attribute::Naked)) + return false; + StringRef EntryAttr = PostInlining ? "instrument-function-entry-inlined" : "instrument-function-entry"; diff --git a/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll b/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll --- a/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll +++ b/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll @@ -99,6 +99,13 @@ ; CHECK: ret } +;; naked functions are not instrumented, otherwise the argument registers +;; and the return address register (if present) would be clobbered. +define void @naked() naked { entry: ret void } +; CHECK-LABEL: define void @naked( +; CHECK-LABEL-NEXT: entry: +; CHECK-LABEL-NEXT: ret void + ; The attributes are "consumed" when the instrumentation is inserted. ; CHECK: attributes ; CHECK-NOT: instrument-function