[TSAN] Add option to allow instrumenting reads of reads-before-writes
authorDmitry Vyukov <dvyukov@google.com>
Fri, 15 May 2020 12:14:18 +0000 (14:14 +0200)
committerDmitry Vyukov <dvyukov@google.com>
Fri, 15 May 2020 14:08:44 +0000 (16:08 +0200)
Add -tsan-instrument-read-before-write which allows instrumenting reads
of reads-before-writes.

This is required for KCSAN [1], where under certain configurations plain
writes behave differently (e.g. aligned writes up to word size may be
treated as atomic). In order to avoid missing potential data races due
to plain RMW operations ("x++" etc.), we will require instrumenting
reads of reads-before-writes.

[1] https://github.com/google/ktsan/wiki/KCSAN

Author: melver (Marco Elver)
Reviewed-in: https://reviews.llvm.org/D79983

llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
llvm/test/Instrumentation/ThreadSanitizer/read_before_write.ll

index 793ef44..313fe74 100644 (file)
@@ -72,6 +72,10 @@ static cl::opt<bool>  ClDistinguishVolatile(
     "tsan-distinguish-volatile", cl::init(false),
     cl::desc("Emit special instrumentation for accesses to volatiles"),
     cl::Hidden);
+static cl::opt<bool>  ClInstrumentReadBeforeWrite(
+    "tsan-instrument-read-before-write", cl::init(false),
+    cl::desc("Do not eliminate read instrumentation for read-before-writes"),
+    cl::Hidden);
 
 STATISTIC(NumInstrumentedReads, "Number of instrumented reads");
 STATISTIC(NumInstrumentedWrites, "Number of instrumented writes");
@@ -413,7 +417,7 @@ void ThreadSanitizer::chooseInstructionsToInstrument(
       Value *Addr = Load->getPointerOperand();
       if (!shouldInstrumentReadWriteFromAddress(I->getModule(), Addr))
         continue;
-      if (WriteTargets.count(Addr)) {
+      if (!ClInstrumentReadBeforeWrite && WriteTargets.count(Addr)) {
         // We will write to this temp, so no reason to analyze the read.
         NumOmittedReadsBeforeWrite++;
         continue;
index c15ab13..33c4f3a 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: opt < %s -tsan -S | FileCheck %s
+; RUN: opt < %s -tsan -tsan-instrument-read-before-write -S | FileCheck %s --check-prefixes=CHECK,CHECK-UNOPT
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
 
@@ -11,6 +12,7 @@ entry:
 }
 ; CHECK: define void @IncrementMe
 ; CHECK-NOT: __tsan_read
+; CHECK-UNOPT: __tsan_read
 ; CHECK: __tsan_write
 ; CHECK: ret void