]> granicus.if.org Git - clang/commitdiff
[InstrProf] Use atomic profile counter updates for TSan
authorVedant Kumar <vsk@apple.com>
Thu, 16 Aug 2018 22:24:47 +0000 (22:24 +0000)
committerVedant Kumar <vsk@apple.com>
Thu, 16 Aug 2018 22:24:47 +0000 (22:24 +0000)
Thread sanitizer instrumentation fails to skip all loads and stores to
profile counters. This can happen if profile counter updates are merged:

  %.sink = phi i64* ...
  %pgocount5 = load i64, i64* %.sink
  %27 = add i64 %pgocount5, 1
  %28 = bitcast i64* %.sink to i8*
  call void @__tsan_write8(i8* %28)
  store i64 %27, i64* %.sink

To suppress TSan diagnostics about racy counter updates, make the
counter updates atomic when TSan is enabled. If there's general interest
in this mode it can be surfaced as a clang/swift driver option.

Testing: check-{llvm,clang,profile}

rdar://40477803

Differential Revision: https://reviews.llvm.org/D50867

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@339955 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/BackendUtil.cpp
test/CodeGen/tsan-instrprof-atomic.c [new file with mode: 0644]

index 415bd9626220a656b97a4bb73dae11375a3fd9dc..826ac267c688adcfcedeb584c299e449012a3c27 100644 (file)
@@ -653,6 +653,11 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
     InstrProfOptions Options;
     Options.NoRedZone = CodeGenOpts.DisableRedZone;
     Options.InstrProfileOutput = CodeGenOpts.InstrProfileOutput;
+
+    // TODO: Surface the option to emit atomic profile counter increments at
+    // the driver level.
+    Options.Atomic = LangOpts.Sanitize.has(SanitizerKind::Thread);
+
     MPM.add(createInstrProfilingLegacyPass(Options));
   }
   if (CodeGenOpts.hasProfileIRInstr()) {
diff --git a/test/CodeGen/tsan-instrprof-atomic.c b/test/CodeGen/tsan-instrprof-atomic.c
new file mode 100644 (file)
index 0000000..b7f99e7
--- /dev/null
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 %s -emit-llvm -fprofile-instrument=clang -fsanitize=thread -o - | FileCheck %s
+
+// CHECK: define void @foo
+// CHECK-NOT: load {{.*}}foo
+// CHECK: ret void
+void foo() {}