diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -441,6 +441,11 @@ // the module constructor. if (F.getName() == kTsanModuleCtorName) return false; + // Naked functions can not have prologue/epilogue + // (__tsan_func_entry/__tsan_func_exit) generated, so don't instrument them at + // all. + if (F.hasFnAttribute(Attribute::Naked)) + return false; initialize(*F.getParent()); SmallVector AllLoadsAndStores; SmallVector LocalLoadsAndStores; diff --git a/llvm/test/Instrumentation/ThreadSanitizer/tsan_basic.ll b/llvm/test/Instrumentation/ThreadSanitizer/tsan_basic.ll --- a/llvm/test/Instrumentation/ThreadSanitizer/tsan_basic.ll +++ b/llvm/test/Instrumentation/ThreadSanitizer/tsan_basic.ll @@ -78,5 +78,18 @@ call void @SwiftError(i8** %0) ret void } + +; CHECK-LABEL: @NakedTest(i32* %a) +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: %tmp1 = load i32, i32* %a, align 4 +; CHECK-NEXT: ret i32 %tmp1 +define i32 @NakedTest(i32* %a) naked sanitize_thread { + call void @foo() + %tmp1 = load i32, i32* %a, align 4 + ret i32 %tmp1 +} + +declare void @foo() nounwind + ; CHECK: define internal void @tsan.module_ctor() ; CHECK: call void @__tsan_init()