1; RUN: opt < %s -tsan -S | FileCheck --check-prefixes=CHECK,CHECK-OPT %s
2; RUN: opt < %s -tsan -tsan-instrument-read-before-write -S | FileCheck %s --check-prefixes=CHECK,CHECK-UNOPT
3; RUN: opt < %s -tsan -tsan-compound-read-before-write -S | FileCheck %s --check-prefixes=CHECK,CHECK-COMPOUND
4; RUN: opt < %s -tsan -tsan-distinguish-volatile -tsan-compound-read-before-write -S | FileCheck %s --check-prefixes=CHECK,CHECK-COMPOUND-VOLATILE
5
6target 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"
7
8define void @IncrementMe(i32* nocapture %ptr) nounwind uwtable sanitize_thread {
9entry:
10  %0 = load i32, i32* %ptr, align 4
11  %inc = add nsw i32 %0, 1
12  store i32 %inc, i32* %ptr, align 4
13  ret void
14}
15; CHECK-LABEL: define void @IncrementMe
16; CHECK-OPT-NOT: __tsan_read4
17; CHECK-COMPOUND-NOT: __tsan_read4
18; CHECK-UNOPT: __tsan_read4
19; CHECK-OPT: __tsan_write4
20; CHECK-UNOPT: __tsan_write4
21; CHECK-COMPOUND: __tsan_read_write4
22; CHECK: ret void
23
24define void @IncrementMeWithCallInBetween(i32* nocapture %ptr) nounwind uwtable sanitize_thread {
25entry:
26  %0 = load i32, i32* %ptr, align 4
27  %inc = add nsw i32 %0, 1
28  call void @foo()
29  store i32 %inc, i32* %ptr, align 4
30  ret void
31}
32
33; CHECK-LABEL: define void @IncrementMeWithCallInBetween
34; CHECK: __tsan_read4
35; CHECK: __tsan_write4
36; CHECK: ret void
37
38declare void @foo()
39
40define void @VolatileLoad(i32* nocapture %ptr) nounwind uwtable sanitize_thread {
41entry:
42  %0 = load volatile i32, i32* %ptr, align 4
43  %inc = add nsw i32 %0, 1
44  store i32 %inc, i32* %ptr, align 4
45  ret void
46}
47; CHECK-LABEL: define void @VolatileLoad
48; CHECK-COMPOUND-NOT: __tsan_read4
49; CHECK-COMPOUND-VOLATILE: __tsan_volatile_read4
50; CHECK-COMPOUND: __tsan_read_write4
51; CHECK-COMPOUND-VOLATILE: __tsan_write4
52; CHECK: ret void
53
54define void @VolatileStore(i32* nocapture %ptr) nounwind uwtable sanitize_thread {
55entry:
56  %0 = load i32, i32* %ptr, align 4
57  %inc = add nsw i32 %0, 1
58  store volatile i32 %inc, i32* %ptr, align 4
59  ret void
60}
61; CHECK-LABEL: define void @VolatileStore
62; CHECK-COMPOUND-NOT: __tsan_read4
63; CHECK-COMPOUND-VOLATILE: __tsan_read4
64; CHECK-COMPOUND: __tsan_read_write4
65; CHECK-COMPOUND-VOLATILE: __tsan_volatile_write4
66; CHECK: ret void
67
68define void @VolatileBoth(i32* nocapture %ptr) nounwind uwtable sanitize_thread {
69entry:
70  %0 = load volatile i32, i32* %ptr, align 4
71  %inc = add nsw i32 %0, 1
72  store volatile i32 %inc, i32* %ptr, align 4
73  ret void
74}
75; CHECK-LABEL: define void @VolatileBoth
76; CHECK-COMPOUND-NOT: __tsan_read4
77; CHECK-COMPOUND-VOLATILE: __tsan_volatile_read4
78; CHECK-COMPOUND: __tsan_read_write4
79; CHECK-COMPOUND-VOLATILE: __tsan_volatile_write4
80; CHECK: ret void
81
82