1; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
2; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck %s
3; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=2 -S | FileCheck %s
4
5target 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"
6target triple = "x86_64-unknown-linux-gnu"
7
8; atomicrmw xchg: store clean shadow, return clean shadow
9
10define i32 @AtomicRmwXchg(i32* %p, i32 %x) sanitize_memory {
11entry:
12  %0 = atomicrmw xchg i32* %p, i32 %x seq_cst
13  ret i32 %0
14}
15
16; CHECK-LABEL: @AtomicRmwXchg
17; CHECK: store i32 0,
18; CHECK: atomicrmw xchg {{.*}} seq_cst
19; CHECK: store i32 0, {{.*}} @__msan_retval_tls
20; CHECK: ret i32
21
22
23; atomicrmw max: exactly the same as above
24
25define i32 @AtomicRmwMax(i32* %p, i32 %x) sanitize_memory {
26entry:
27  %0 = atomicrmw max i32* %p, i32 %x seq_cst
28  ret i32 %0
29}
30
31; CHECK-LABEL: @AtomicRmwMax
32; CHECK: store i32 0,
33; CHECK: atomicrmw max {{.*}} seq_cst
34; CHECK: store i32 0, {{.*}} @__msan_retval_tls
35; CHECK: ret i32
36
37
38; cmpxchg: the same as above, but also check %a shadow
39
40define i32 @Cmpxchg(i32* %p, i32 %a, i32 %b) sanitize_memory {
41entry:
42  %pair = cmpxchg i32* %p, i32 %a, i32 %b seq_cst seq_cst
43  %0 = extractvalue { i32, i1 } %pair, 0
44  ret i32 %0
45}
46
47; CHECK-LABEL: @Cmpxchg
48; CHECK: store { i32, i1 } zeroinitializer,
49; CHECK: icmp
50; CHECK: br
51; CHECK: @__msan_warning
52; CHECK: cmpxchg {{.*}} seq_cst seq_cst
53; CHECK: store i32 0, {{.*}} @__msan_retval_tls
54; CHECK: ret i32
55
56
57; relaxed cmpxchg: bump up to "release monotonic"
58
59define i32 @CmpxchgMonotonic(i32* %p, i32 %a, i32 %b) sanitize_memory {
60entry:
61  %pair = cmpxchg i32* %p, i32 %a, i32 %b monotonic monotonic
62  %0 = extractvalue { i32, i1 } %pair, 0
63  ret i32 %0
64}
65
66; CHECK-LABEL: @CmpxchgMonotonic
67; CHECK: store { i32, i1 } zeroinitializer,
68; CHECK: icmp
69; CHECK: br
70; CHECK: @__msan_warning
71; CHECK: cmpxchg {{.*}} release monotonic
72; CHECK: store i32 0, {{.*}} @__msan_retval_tls
73; CHECK: ret i32
74
75
76; atomic load: preserve alignment, load shadow value after app value
77
78define i32 @AtomicLoad(i32* %p) sanitize_memory {
79entry:
80  %0 = load atomic i32, i32* %p seq_cst, align 16
81  ret i32 %0
82}
83
84; CHECK-LABEL: @AtomicLoad
85; CHECK: load atomic i32, i32* {{.*}} seq_cst, align 16
86; CHECK: [[SHADOW:%[01-9a-z_]+]] = load i32, i32* {{.*}}, align 16
87; CHECK: store i32 {{.*}}[[SHADOW]], {{.*}} @__msan_retval_tls
88; CHECK: ret i32
89
90
91; atomic load: preserve alignment, load shadow value after app value
92
93define i32 @AtomicLoadAcquire(i32* %p) sanitize_memory {
94entry:
95  %0 = load atomic i32, i32* %p acquire, align 16
96  ret i32 %0
97}
98
99; CHECK-LABEL: @AtomicLoadAcquire
100; CHECK: load atomic i32, i32* {{.*}} acquire, align 16
101; CHECK: [[SHADOW:%[01-9a-z_]+]] = load i32, i32* {{.*}}, align 16
102; CHECK: store i32 {{.*}}[[SHADOW]], {{.*}} @__msan_retval_tls
103; CHECK: ret i32
104
105
106; atomic load monotonic: bump up to load acquire
107
108define i32 @AtomicLoadMonotonic(i32* %p) sanitize_memory {
109entry:
110  %0 = load atomic i32, i32* %p monotonic, align 16
111  ret i32 %0
112}
113
114; CHECK-LABEL: @AtomicLoadMonotonic
115; CHECK: load atomic i32, i32* {{.*}} acquire, align 16
116; CHECK: [[SHADOW:%[01-9a-z_]+]] = load i32, i32* {{.*}}, align 16
117; CHECK: store i32 {{.*}}[[SHADOW]], {{.*}} @__msan_retval_tls
118; CHECK: ret i32
119
120
121; atomic load unordered: bump up to load acquire
122
123define i32 @AtomicLoadUnordered(i32* %p) sanitize_memory {
124entry:
125  %0 = load atomic i32, i32* %p unordered, align 16
126  ret i32 %0
127}
128
129; CHECK-LABEL: @AtomicLoadUnordered
130; CHECK: load atomic i32, i32* {{.*}} acquire, align 16
131; CHECK: [[SHADOW:%[01-9a-z_]+]] = load i32, i32* {{.*}}, align 16
132; CHECK: store i32 {{.*}}[[SHADOW]], {{.*}} @__msan_retval_tls
133; CHECK: ret i32
134
135
136; atomic store: preserve alignment, store clean shadow value before app value
137
138define void @AtomicStore(i32* %p, i32 %x) sanitize_memory {
139entry:
140  store atomic i32 %x, i32* %p seq_cst, align 16
141  ret void
142}
143
144; CHECK-LABEL: @AtomicStore
145; CHECK-NOT: @__msan_param_tls
146; CHECK: store i32 0, i32* {{.*}}, align 16
147; CHECK: store atomic i32 %x, i32* %p seq_cst, align 16
148; CHECK: ret void
149
150
151; atomic store: preserve alignment, store clean shadow value before app value
152
153define void @AtomicStoreRelease(i32* %p, i32 %x) sanitize_memory {
154entry:
155  store atomic i32 %x, i32* %p release, align 16
156  ret void
157}
158
159; CHECK-LABEL: @AtomicStoreRelease
160; CHECK-NOT: @__msan_param_tls
161; CHECK: store i32 0, i32* {{.*}}, align 16
162; CHECK: store atomic i32 %x, i32* %p release, align 16
163; CHECK: ret void
164
165
166; atomic store monotonic: bumped up to store release
167
168define void @AtomicStoreMonotonic(i32* %p, i32 %x) sanitize_memory {
169entry:
170  store atomic i32 %x, i32* %p monotonic, align 16
171  ret void
172}
173
174; CHECK-LABEL: @AtomicStoreMonotonic
175; CHECK-NOT: @__msan_param_tls
176; CHECK: store i32 0, i32* {{.*}}, align 16
177; CHECK: store atomic i32 %x, i32* %p release, align 16
178; CHECK: ret void
179
180
181; atomic store unordered: bumped up to store release
182
183define void @AtomicStoreUnordered(i32* %p, i32 %x) sanitize_memory {
184entry:
185  store atomic i32 %x, i32* %p unordered, align 16
186  ret void
187}
188
189; CHECK-LABEL: @AtomicStoreUnordered
190; CHECK-NOT: @__msan_param_tls
191; CHECK: store i32 0, i32* {{.*}}, align 16
192; CHECK: store atomic i32 %x, i32* %p release, align 16
193; CHECK: ret void
194