Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c	(revision 219914)
+++ gcc/gimplify.c	(working copy)
@@ -9250,7 +9250,8 @@ gimplify_function_tree (tree fndecl)
       bind = new_bind;
     }
 
-  if (flag_sanitize & SANITIZE_THREAD)
+  if ((flag_sanitize & SANITIZE_THREAD) != 0
+      && !lookup_attribute ("no_sanitize_thread", DECL_ATTRIBUTES (fndecl)))
     {
       gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
       gimple tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY);
Index: gcc/testsuite/c-c++-common/tsan/step.c
===================================================================
--- gcc/testsuite/c-c++-common/tsan/step.c	(revision 0)
+++ gcc/testsuite/c-c++-common/tsan/step.c	(working copy)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+extern int sched_yield (void);
+static volatile int serial = 0;
+
+__attribute__((no_sanitize_thread))
+void step (int i)
+{
+   while (__atomic_load_n (&serial, __ATOMIC_ACQUIRE) != i - 1)
+     sched_yield();
+   __atomic_store_n (&serial, i, __ATOMIC_RELEASE);
+}
+
+/* { dg-final { scan-assembler-not "__tsan_func_entry" } } */
+/* { dg-final { scan-assembler-not "__tsan_func_exit" } } */
