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