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 5 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" 6 target triple = "x86_64-unknown-linux-gnu" 7 8 ; atomicrmw xchg: store clean shadow, return clean shadow 9 10 define i32 @AtomicRmwXchg(i32* %p, i32 %x) sanitize_memory { 11 entry: 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 25 define i32 @AtomicRmwMax(i32* %p, i32 %x) sanitize_memory { 26 entry: 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 40 define i32 @Cmpxchg(i32* %p, i32 %a, i32 %b) sanitize_memory { 41 entry: 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 59 define i32 @CmpxchgMonotonic(i32* %p, i32 %a, i32 %b) sanitize_memory { 60 entry: 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 78 define i32 @AtomicLoad(i32* %p) sanitize_memory { 79 entry: 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 93 define i32 @AtomicLoadAcquire(i32* %p) sanitize_memory { 94 entry: 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 108 define i32 @AtomicLoadMonotonic(i32* %p) sanitize_memory { 109 entry: 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 123 define i32 @AtomicLoadUnordered(i32* %p) sanitize_memory { 124 entry: 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 138 define void @AtomicStore(i32* %p, i32 %x) sanitize_memory { 139 entry: 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 153 define void @AtomicStoreRelease(i32* %p, i32 %x) sanitize_memory { 154 entry: 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 168 define void @AtomicStoreMonotonic(i32* %p, i32 %x) sanitize_memory { 169 entry: 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 183 define void @AtomicStoreUnordered(i32* %p, i32 %x) sanitize_memory { 184 entry: 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