Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(179)

Side by Side Diff: tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll

Issue 1387963002: Make sure that all globals are internal, except for "start" functions. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix new tests. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 ; This tests each of the supported NaCl atomic instructions for every 1 ; This tests each of the supported NaCl atomic instructions for every
2 ; size allowed. 2 ; size allowed.
3 3
4 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \ 4 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \
5 ; RUN: | FileCheck %s 5 ; RUN: -allow-externally-defined-symbols | FileCheck %s
6 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \ 6 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \
7 ; RUN: | FileCheck --check-prefix=O2 %s 7 ; RUN: -allow-externally-defined-symbols | FileCheck --check-prefix=O2 %s
8 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -Om1 \ 8 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -Om1 \
9 ; RUN: | FileCheck %s 9 ; RUN: -allow-externally-defined-symbols | FileCheck %s
10 10
11 ; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \ 11 ; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
12 ; RUN: --target arm32 -i %s --args -O2 --skip-unimplemented \ 12 ; RUN: --target arm32 -i %s --args -O2 --skip-unimplemented \
13 ; RUN: -allow-externally-defined-symbols \
13 ; RUN: | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \ 14 ; RUN: | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \
14 ; RUN: --check-prefix=ARM32 15 ; RUN: --check-prefix=ARM32
15 16
16 ; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \ 17 ; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
17 ; RUN: --target arm32 -i %s --args -O2 --skip-unimplemented \ 18 ; RUN: --target arm32 -i %s --args -O2 --skip-unimplemented \
19 ; RUN: -allow-externally-defined-symbols \
18 ; RUN: | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \ 20 ; RUN: | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \
19 ; RUN: --check-prefix=ARM32O2 21 ; RUN: --check-prefix=ARM32O2
20 22
21 ; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \ 23 ; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
22 ; RUN: --target arm32 -i %s --args -Om1 --skip-unimplemented \ 24 ; RUN: --target arm32 -i %s --args -Om1 --skip-unimplemented \
25 ; RUN: -allow-externally-defined-symbols \
23 ; RUN: | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \ 26 ; RUN: | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \
24 ; RUN: --check-prefix=ARM32 27 ; RUN: --check-prefix=ARM32
25 28
26 declare i8 @llvm.nacl.atomic.load.i8(i8*, i32) 29 declare i8 @llvm.nacl.atomic.load.i8(i8*, i32)
27 declare i16 @llvm.nacl.atomic.load.i16(i16*, i32) 30 declare i16 @llvm.nacl.atomic.load.i16(i16*, i32)
28 declare i32 @llvm.nacl.atomic.load.i32(i32*, i32) 31 declare i32 @llvm.nacl.atomic.load.i32(i32*, i32)
29 declare i64 @llvm.nacl.atomic.load.i64(i64*, i32) 32 declare i64 @llvm.nacl.atomic.load.i64(i64*, i32)
30 declare void @llvm.nacl.atomic.store.i8(i8, i8*, i32) 33 declare void @llvm.nacl.atomic.store.i8(i8, i8*, i32)
31 declare void @llvm.nacl.atomic.store.i16(i16, i16*, i32) 34 declare void @llvm.nacl.atomic.store.i16(i16, i16*, i32)
32 declare void @llvm.nacl.atomic.store.i32(i32, i32*, i32) 35 declare void @llvm.nacl.atomic.store.i32(i32, i32*, i32)
(...skipping 18 matching lines...) Expand all
51 ; NOTE: The LLC equivalent for 16-bit atomic operations are expanded 54 ; NOTE: The LLC equivalent for 16-bit atomic operations are expanded
52 ; as 32-bit operations. For Subzero, assume that real 16-bit operations 55 ; as 32-bit operations. For Subzero, assume that real 16-bit operations
53 ; will be usable (the validator will be fixed): 56 ; will be usable (the validator will be fixed):
54 ; https://code.google.com/p/nativeclient/issues/detail?id=2981 57 ; https://code.google.com/p/nativeclient/issues/detail?id=2981
55 58
56 ;;; Load 59 ;;; Load
57 60
58 ; x86 guarantees load/store to be atomic if naturally aligned. 61 ; x86 guarantees load/store to be atomic if naturally aligned.
59 ; The PNaCl IR requires all atomic accesses to be naturally aligned. 62 ; The PNaCl IR requires all atomic accesses to be naturally aligned.
60 63
61 define i32 @test_atomic_load_8(i32 %iptr) { 64 define internal i32 @test_atomic_load_8(i32 %iptr) {
62 entry: 65 entry:
63 %ptr = inttoptr i32 %iptr to i8* 66 %ptr = inttoptr i32 %iptr to i8*
64 ; parameter value "6" is for the sequential consistency memory order. 67 ; parameter value "6" is for the sequential consistency memory order.
65 %i = call i8 @llvm.nacl.atomic.load.i8(i8* %ptr, i32 6) 68 %i = call i8 @llvm.nacl.atomic.load.i8(i8* %ptr, i32 6)
66 %i2 = sub i8 %i, 0 69 %i2 = sub i8 %i, 0
67 %r = zext i8 %i2 to i32 70 %r = zext i8 %i2 to i32
68 ret i32 %r 71 ret i32 %r
69 } 72 }
70 ; CHECK-LABEL: test_atomic_load_8 73 ; CHECK-LABEL: test_atomic_load_8
71 ; CHECK: mov {{.*}},DWORD 74 ; CHECK: mov {{.*}},DWORD
72 ; CHECK: mov {{.*}},BYTE 75 ; CHECK: mov {{.*}},BYTE
73 ; ARM32-LABEL: test_atomic_load_8 76 ; ARM32-LABEL: test_atomic_load_8
74 ; ARM32: ldrb r{{[0-9]+}}, [r{{[0-9]+}} 77 ; ARM32: ldrb r{{[0-9]+}}, [r{{[0-9]+}}
75 ; ARM32: dmb 78 ; ARM32: dmb
76 79
77 define i32 @test_atomic_load_16(i32 %iptr) { 80 define internal i32 @test_atomic_load_16(i32 %iptr) {
78 entry: 81 entry:
79 %ptr = inttoptr i32 %iptr to i16* 82 %ptr = inttoptr i32 %iptr to i16*
80 %i = call i16 @llvm.nacl.atomic.load.i16(i16* %ptr, i32 6) 83 %i = call i16 @llvm.nacl.atomic.load.i16(i16* %ptr, i32 6)
81 %i2 = sub i16 %i, 0 84 %i2 = sub i16 %i, 0
82 %r = zext i16 %i2 to i32 85 %r = zext i16 %i2 to i32
83 ret i32 %r 86 ret i32 %r
84 } 87 }
85 ; CHECK-LABEL: test_atomic_load_16 88 ; CHECK-LABEL: test_atomic_load_16
86 ; CHECK: mov {{.*}},DWORD 89 ; CHECK: mov {{.*}},DWORD
87 ; CHECK: mov {{.*}},WORD 90 ; CHECK: mov {{.*}},WORD
88 ; ARM32-LABEL: test_atomic_load_16 91 ; ARM32-LABEL: test_atomic_load_16
89 ; ARM32: ldrh r{{[0-9]+}}, [r{{[0-9]+}} 92 ; ARM32: ldrh r{{[0-9]+}}, [r{{[0-9]+}}
90 ; ARM32: dmb 93 ; ARM32: dmb
91 94
92 define i32 @test_atomic_load_32(i32 %iptr) { 95 define internal i32 @test_atomic_load_32(i32 %iptr) {
93 entry: 96 entry:
94 %ptr = inttoptr i32 %iptr to i32* 97 %ptr = inttoptr i32 %iptr to i32*
95 %r = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) 98 %r = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6)
96 ret i32 %r 99 ret i32 %r
97 } 100 }
98 ; CHECK-LABEL: test_atomic_load_32 101 ; CHECK-LABEL: test_atomic_load_32
99 ; CHECK: mov {{.*}},DWORD 102 ; CHECK: mov {{.*}},DWORD
100 ; CHECK: mov {{.*}},DWORD 103 ; CHECK: mov {{.*}},DWORD
101 ; ARM32-LABEL: test_atomic_load_32 104 ; ARM32-LABEL: test_atomic_load_32
102 ; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}} 105 ; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}}
103 ; ARM32: dmb 106 ; ARM32: dmb
104 107
105 define i64 @test_atomic_load_64(i32 %iptr) { 108 define internal i64 @test_atomic_load_64(i32 %iptr) {
106 entry: 109 entry:
107 %ptr = inttoptr i32 %iptr to i64* 110 %ptr = inttoptr i32 %iptr to i64*
108 %r = call i64 @llvm.nacl.atomic.load.i64(i64* %ptr, i32 6) 111 %r = call i64 @llvm.nacl.atomic.load.i64(i64* %ptr, i32 6)
109 ret i64 %r 112 ret i64 %r
110 } 113 }
111 ; CHECK-LABEL: test_atomic_load_64 114 ; CHECK-LABEL: test_atomic_load_64
112 ; CHECK: movq x{{.*}},QWORD 115 ; CHECK: movq x{{.*}},QWORD
113 ; CHECK: movq QWORD {{.*}},x{{.*}} 116 ; CHECK: movq QWORD {{.*}},x{{.*}}
114 ; ARM32-LABEL: test_atomic_load_64 117 ; ARM32-LABEL: test_atomic_load_64
115 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}} 118 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}
116 ; ARM32: dmb 119 ; ARM32: dmb
117 120
118 define i32 @test_atomic_load_32_with_arith(i32 %iptr) { 121 define internal i32 @test_atomic_load_32_with_arith(i32 %iptr) {
119 entry: 122 entry:
120 br label %next 123 br label %next
121 124
122 next: 125 next:
123 %ptr = inttoptr i32 %iptr to i32* 126 %ptr = inttoptr i32 %iptr to i32*
124 %r = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) 127 %r = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6)
125 %r2 = sub i32 32, %r 128 %r2 = sub i32 32, %r
126 ret i32 %r2 129 ret i32 %r2
127 } 130 }
128 ; CHECK-LABEL: test_atomic_load_32_with_arith 131 ; CHECK-LABEL: test_atomic_load_32_with_arith
129 ; CHECK: mov {{.*}},DWORD 132 ; CHECK: mov {{.*}},DWORD
130 ; The next instruction may be a separate load or folded into an add. 133 ; The next instruction may be a separate load or folded into an add.
131 ; 134 ;
132 ; In O2 mode, we know that the load and sub are going to be fused. 135 ; In O2 mode, we know that the load and sub are going to be fused.
133 ; O2-LABEL: test_atomic_load_32_with_arith 136 ; O2-LABEL: test_atomic_load_32_with_arith
134 ; O2: mov {{.*}},DWORD 137 ; O2: mov {{.*}},DWORD
135 ; O2: sub {{.*}},DWORD 138 ; O2: sub {{.*}},DWORD
136 ; ARM32-LABEL: test_atomic_load_32_with_arith 139 ; ARM32-LABEL: test_atomic_load_32_with_arith
137 ; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}} 140 ; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}}
138 ; ARM32: dmb 141 ; ARM32: dmb
139 142
140 define i32 @test_atomic_load_32_ignored(i32 %iptr) { 143 define internal i32 @test_atomic_load_32_ignored(i32 %iptr) {
141 entry: 144 entry:
142 %ptr = inttoptr i32 %iptr to i32* 145 %ptr = inttoptr i32 %iptr to i32*
143 %ignored = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) 146 %ignored = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6)
144 ret i32 0 147 ret i32 0
145 } 148 }
146 ; CHECK-LABEL: test_atomic_load_32_ignored 149 ; CHECK-LABEL: test_atomic_load_32_ignored
147 ; CHECK: mov {{.*}},DWORD 150 ; CHECK: mov {{.*}},DWORD
148 ; CHECK: mov {{.*}},DWORD 151 ; CHECK: mov {{.*}},DWORD
149 ; O2-LABEL: test_atomic_load_32_ignored 152 ; O2-LABEL: test_atomic_load_32_ignored
150 ; O2: mov {{.*}},DWORD 153 ; O2: mov {{.*}},DWORD
151 ; O2: mov {{.*}},DWORD 154 ; O2: mov {{.*}},DWORD
152 ; ARM32-LABEL: test_atomic_load_32_ignored 155 ; ARM32-LABEL: test_atomic_load_32_ignored
153 ; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}} 156 ; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}}
154 ; ARM32: dmb 157 ; ARM32: dmb
155 158
156 define i64 @test_atomic_load_64_ignored(i32 %iptr) { 159 define internal i64 @test_atomic_load_64_ignored(i32 %iptr) {
157 entry: 160 entry:
158 %ptr = inttoptr i32 %iptr to i64* 161 %ptr = inttoptr i32 %iptr to i64*
159 %ignored = call i64 @llvm.nacl.atomic.load.i64(i64* %ptr, i32 6) 162 %ignored = call i64 @llvm.nacl.atomic.load.i64(i64* %ptr, i32 6)
160 ret i64 0 163 ret i64 0
161 } 164 }
162 ; CHECK-LABEL: test_atomic_load_64_ignored 165 ; CHECK-LABEL: test_atomic_load_64_ignored
163 ; CHECK: movq x{{.*}},QWORD 166 ; CHECK: movq x{{.*}},QWORD
164 ; CHECK: movq QWORD {{.*}},x{{.*}} 167 ; CHECK: movq QWORD {{.*}},x{{.*}}
165 ; ARM32-LABEL: test_atomic_load_64_ignored 168 ; ARM32-LABEL: test_atomic_load_64_ignored
166 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}} 169 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}
167 ; ARM32: dmb 170 ; ARM32: dmb
168 171
169 ;;; Store 172 ;;; Store
170 173
171 define void @test_atomic_store_8(i32 %iptr, i32 %v) { 174 define internal void @test_atomic_store_8(i32 %iptr, i32 %v) {
172 entry: 175 entry:
173 %truncv = trunc i32 %v to i8 176 %truncv = trunc i32 %v to i8
174 %ptr = inttoptr i32 %iptr to i8* 177 %ptr = inttoptr i32 %iptr to i8*
175 call void @llvm.nacl.atomic.store.i8(i8 %truncv, i8* %ptr, i32 6) 178 call void @llvm.nacl.atomic.store.i8(i8 %truncv, i8* %ptr, i32 6)
176 ret void 179 ret void
177 } 180 }
178 ; CHECK-LABEL: test_atomic_store_8 181 ; CHECK-LABEL: test_atomic_store_8
179 ; CHECK: mov BYTE 182 ; CHECK: mov BYTE
180 ; CHECK: mfence 183 ; CHECK: mfence
181 ; ARM32-LABEL: test_atomic_store_8 184 ; ARM32-LABEL: test_atomic_store_8
182 ; ARM32: dmb 185 ; ARM32: dmb
183 ; ARM32: strb r{{[0-9]+}}, [r{{[0-9]+}} 186 ; ARM32: strb r{{[0-9]+}}, [r{{[0-9]+}}
184 ; ARM32: dmb 187 ; ARM32: dmb
185 188
186 define void @test_atomic_store_16(i32 %iptr, i32 %v) { 189 define internal void @test_atomic_store_16(i32 %iptr, i32 %v) {
187 entry: 190 entry:
188 %truncv = trunc i32 %v to i16 191 %truncv = trunc i32 %v to i16
189 %ptr = inttoptr i32 %iptr to i16* 192 %ptr = inttoptr i32 %iptr to i16*
190 call void @llvm.nacl.atomic.store.i16(i16 %truncv, i16* %ptr, i32 6) 193 call void @llvm.nacl.atomic.store.i16(i16 %truncv, i16* %ptr, i32 6)
191 ret void 194 ret void
192 } 195 }
193 ; CHECK-LABEL: test_atomic_store_16 196 ; CHECK-LABEL: test_atomic_store_16
194 ; CHECK: mov WORD 197 ; CHECK: mov WORD
195 ; CHECK: mfence 198 ; CHECK: mfence
196 ; ARM32-LABEL: test_atomic_store_16 199 ; ARM32-LABEL: test_atomic_store_16
197 ; ARM32: dmb 200 ; ARM32: dmb
198 ; ARM32: strh r{{[0-9]+}}, [r{{[0-9]+}} 201 ; ARM32: strh r{{[0-9]+}}, [r{{[0-9]+}}
199 ; ARM32: dmb 202 ; ARM32: dmb
200 203
201 define void @test_atomic_store_32(i32 %iptr, i32 %v) { 204 define internal void @test_atomic_store_32(i32 %iptr, i32 %v) {
202 entry: 205 entry:
203 %ptr = inttoptr i32 %iptr to i32* 206 %ptr = inttoptr i32 %iptr to i32*
204 call void @llvm.nacl.atomic.store.i32(i32 %v, i32* %ptr, i32 6) 207 call void @llvm.nacl.atomic.store.i32(i32 %v, i32* %ptr, i32 6)
205 ret void 208 ret void
206 } 209 }
207 ; CHECK-LABEL: test_atomic_store_32 210 ; CHECK-LABEL: test_atomic_store_32
208 ; CHECK: mov DWORD 211 ; CHECK: mov DWORD
209 ; CHECK: mfence 212 ; CHECK: mfence
210 ; ARM32-LABEL: test_atomic_store_32 213 ; ARM32-LABEL: test_atomic_store_32
211 ; ARM32: dmb 214 ; ARM32: dmb
212 ; ARM32: str r{{[0-9]+}}, [r{{[0-9]+}} 215 ; ARM32: str r{{[0-9]+}}, [r{{[0-9]+}}
213 ; ARM32: dmb 216 ; ARM32: dmb
214 217
215 define void @test_atomic_store_64(i32 %iptr, i64 %v) { 218 define internal void @test_atomic_store_64(i32 %iptr, i64 %v) {
216 entry: 219 entry:
217 %ptr = inttoptr i32 %iptr to i64* 220 %ptr = inttoptr i32 %iptr to i64*
218 call void @llvm.nacl.atomic.store.i64(i64 %v, i64* %ptr, i32 6) 221 call void @llvm.nacl.atomic.store.i64(i64 %v, i64* %ptr, i32 6)
219 ret void 222 ret void
220 } 223 }
221 ; CHECK-LABEL: test_atomic_store_64 224 ; CHECK-LABEL: test_atomic_store_64
222 ; CHECK: movq x{{.*}},QWORD 225 ; CHECK: movq x{{.*}},QWORD
223 ; CHECK: movq QWORD {{.*}},x{{.*}} 226 ; CHECK: movq QWORD {{.*}},x{{.*}}
224 ; CHECK: mfence 227 ; CHECK: mfence
225 ; ARM32-LABEL: test_atomic_store_64 228 ; ARM32-LABEL: test_atomic_store_64
226 ; ARM32: dmb 229 ; ARM32: dmb
227 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [[MEM:.*]] 230 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [[MEM:.*]]
228 ; ARM32: strexd [[S:r[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}, [[MEM]] 231 ; ARM32: strexd [[S:r[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}, [[MEM]]
229 ; ARM32: cmp [[S]], #0 232 ; ARM32: cmp [[S]], #0
230 ; ARM32: bne 233 ; ARM32: bne
231 ; ARM32: dmb 234 ; ARM32: dmb
232 235
233 define void @test_atomic_store_64_const(i32 %iptr) { 236 define internal void @test_atomic_store_64_const(i32 %iptr) {
234 entry: 237 entry:
235 %ptr = inttoptr i32 %iptr to i64* 238 %ptr = inttoptr i32 %iptr to i64*
236 call void @llvm.nacl.atomic.store.i64(i64 12345678901234, i64* %ptr, i32 6) 239 call void @llvm.nacl.atomic.store.i64(i64 12345678901234, i64* %ptr, i32 6)
237 ret void 240 ret void
238 } 241 }
239 ; CHECK-LABEL: test_atomic_store_64_const 242 ; CHECK-LABEL: test_atomic_store_64_const
240 ; CHECK: mov {{.*}},0x73ce2ff2 243 ; CHECK: mov {{.*}},0x73ce2ff2
241 ; CHECK: mov {{.*}},0xb3a 244 ; CHECK: mov {{.*}},0xb3a
242 ; CHECK: movq x{{.*}},QWORD 245 ; CHECK: movq x{{.*}},QWORD
243 ; CHECK: movq QWORD {{.*}},x{{.*}} 246 ; CHECK: movq QWORD {{.*}},x{{.*}}
244 ; CHECK: mfence 247 ; CHECK: mfence
245 ; ARM32-LABEL: test_atomic_store_64_const 248 ; ARM32-LABEL: test_atomic_store_64_const
246 ; ARM32: dmb 249 ; ARM32: dmb
247 ; ARM32: movw [[T0:r[0-9]+]], #12274 250 ; ARM32: movw [[T0:r[0-9]+]], #12274
248 ; ARM32: movt [[T0]], #29646 251 ; ARM32: movt [[T0]], #29646
249 ; ARM32: movw r{{[0-9]+}}, #2874 252 ; ARM32: movw r{{[0-9]+}}, #2874
250 ; ARM32: .L[[RETRY:.*]]: 253 ; ARM32: .L[[RETRY:.*]]:
251 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [[MEM:.*]] 254 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [[MEM:.*]]
252 ; ARM32: strexd [[S:r[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}, [[MEM]] 255 ; ARM32: strexd [[S:r[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}, [[MEM]]
253 ; ARM32: cmp [[S]], #0 256 ; ARM32: cmp [[S]], #0
254 ; ARM32: bne .L[[RETRY]] 257 ; ARM32: bne .L[[RETRY]]
255 ; ARM32: dmb 258 ; ARM32: dmb
256 259
257 ;;; RMW 260 ;;; RMW
258 261
259 ;; add 262 ;; add
260 263
261 define i32 @test_atomic_rmw_add_8(i32 %iptr, i32 %v) { 264 define internal i32 @test_atomic_rmw_add_8(i32 %iptr, i32 %v) {
262 entry: 265 entry:
263 %trunc = trunc i32 %v to i8 266 %trunc = trunc i32 %v to i8
264 %ptr = inttoptr i32 %iptr to i8* 267 %ptr = inttoptr i32 %iptr to i8*
265 ; "1" is an atomic add, and "6" is sequential consistency. 268 ; "1" is an atomic add, and "6" is sequential consistency.
266 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 1, i8* %ptr, i8 %trunc, i32 6) 269 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 1, i8* %ptr, i8 %trunc, i32 6)
267 %a_ext = zext i8 %a to i32 270 %a_ext = zext i8 %a to i32
268 ret i32 %a_ext 271 ret i32 %a_ext
269 } 272 }
270 ; CHECK-LABEL: test_atomic_rmw_add_8 273 ; CHECK-LABEL: test_atomic_rmw_add_8
271 ; CHECK: lock xadd BYTE {{.*}},[[REG:.*]] 274 ; CHECK: lock xadd BYTE {{.*}},[[REG:.*]]
272 ; CHECK: {{mov|movzx}} {{.*}},[[REG]] 275 ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
273 ; ARM32-LABEL: test_atomic_rmw_add_8 276 ; ARM32-LABEL: test_atomic_rmw_add_8
274 ; ARM32: dmb 277 ; ARM32: dmb
275 ; ARM32: ldrexb 278 ; ARM32: ldrexb
276 ; ARM32: add 279 ; ARM32: add
277 ; ARM32: strexb 280 ; ARM32: strexb
278 ; ARM32: bne 281 ; ARM32: bne
279 ; ARM32: dmb 282 ; ARM32: dmb
280 283
281 define i32 @test_atomic_rmw_add_16(i32 %iptr, i32 %v) { 284 define internal i32 @test_atomic_rmw_add_16(i32 %iptr, i32 %v) {
282 entry: 285 entry:
283 %trunc = trunc i32 %v to i16 286 %trunc = trunc i32 %v to i16
284 %ptr = inttoptr i32 %iptr to i16* 287 %ptr = inttoptr i32 %iptr to i16*
285 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 1, i16* %ptr, i16 %trunc, i32 6) 288 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 1, i16* %ptr, i16 %trunc, i32 6)
286 %a_ext = zext i16 %a to i32 289 %a_ext = zext i16 %a to i32
287 ret i32 %a_ext 290 ret i32 %a_ext
288 } 291 }
289 ; CHECK-LABEL: test_atomic_rmw_add_16 292 ; CHECK-LABEL: test_atomic_rmw_add_16
290 ; CHECK: lock xadd WORD {{.*}},[[REG:.*]] 293 ; CHECK: lock xadd WORD {{.*}},[[REG:.*]]
291 ; CHECK: {{mov|movzx}} {{.*}},[[REG]] 294 ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
292 ; ARM32-LABEL: test_atomic_rmw_add_16 295 ; ARM32-LABEL: test_atomic_rmw_add_16
293 ; ARM32: dmb 296 ; ARM32: dmb
294 ; ARM32: ldrexh 297 ; ARM32: ldrexh
295 ; ARM32: add 298 ; ARM32: add
296 ; ARM32: strexh 299 ; ARM32: strexh
297 ; ARM32: bne 300 ; ARM32: bne
298 ; ARM32: dmb 301 ; ARM32: dmb
299 302
300 define i32 @test_atomic_rmw_add_32(i32 %iptr, i32 %v) { 303 define internal i32 @test_atomic_rmw_add_32(i32 %iptr, i32 %v) {
301 entry: 304 entry:
302 %ptr = inttoptr i32 %iptr to i32* 305 %ptr = inttoptr i32 %iptr to i32*
303 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %ptr, i32 %v, i32 6) 306 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %ptr, i32 %v, i32 6)
304 ret i32 %a 307 ret i32 %a
305 } 308 }
306 ; CHECK-LABEL: test_atomic_rmw_add_32 309 ; CHECK-LABEL: test_atomic_rmw_add_32
307 ; CHECK: lock xadd DWORD {{.*}},[[REG:.*]] 310 ; CHECK: lock xadd DWORD {{.*}},[[REG:.*]]
308 ; CHECK: mov {{.*}},[[REG]] 311 ; CHECK: mov {{.*}},[[REG]]
309 ; ARM32-LABEL: test_atomic_rmw_add_32 312 ; ARM32-LABEL: test_atomic_rmw_add_32
310 ; ARM32: dmb 313 ; ARM32: dmb
311 ; ARM32: ldrex 314 ; ARM32: ldrex
312 ; ARM32: add 315 ; ARM32: add
313 ; ARM32: strex 316 ; ARM32: strex
314 ; ARM32: bne 317 ; ARM32: bne
315 ; ARM32: dmb 318 ; ARM32: dmb
316 319
317 define i64 @test_atomic_rmw_add_64(i32 %iptr, i64 %v) { 320 define internal i64 @test_atomic_rmw_add_64(i32 %iptr, i64 %v) {
318 entry: 321 entry:
319 %ptr = inttoptr i32 %iptr to i64* 322 %ptr = inttoptr i32 %iptr to i64*
320 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v, i32 6) 323 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v, i32 6)
321 ret i64 %a 324 ret i64 %a
322 } 325 }
323 ; CHECK-LABEL: test_atomic_rmw_add_64 326 ; CHECK-LABEL: test_atomic_rmw_add_64
324 ; CHECK: push ebx 327 ; CHECK: push ebx
325 ; CHECK: mov eax,DWORD PTR [{{.*}}] 328 ; CHECK: mov eax,DWORD PTR [{{.*}}]
326 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4] 329 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
327 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax 330 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax
(...skipping 10 matching lines...) Expand all
338 ; ARM32-LABEL: test_atomic_rmw_add_64 341 ; ARM32-LABEL: test_atomic_rmw_add_64
339 ; ARM32: dmb 342 ; ARM32: dmb
340 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 343 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
341 ; ARM32: adds 344 ; ARM32: adds
342 ; ARM32-NEXT: adc 345 ; ARM32-NEXT: adc
343 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 346 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
344 ; ARM32: bne 347 ; ARM32: bne
345 ; ARM32: dmb 348 ; ARM32: dmb
346 349
347 ; Same test as above, but with a global address to test FakeUse issues. 350 ; Same test as above, but with a global address to test FakeUse issues.
348 define i64 @test_atomic_rmw_add_64_global(i64 %v) { 351 define internal i64 @test_atomic_rmw_add_64_global(i64 %v) {
349 entry: 352 entry:
350 %ptr = bitcast [8 x i8]* @Global64 to i64* 353 %ptr = bitcast [8 x i8]* @Global64 to i64*
351 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v, i32 6) 354 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v, i32 6)
352 ret i64 %a 355 ret i64 %a
353 } 356 }
354 ; CHECK-LABEL: test_atomic_rmw_add_64_global 357 ; CHECK-LABEL: test_atomic_rmw_add_64_global
355 ; ARM32-LABEL: test_atomic_rmw_add_64_global 358 ; ARM32-LABEL: test_atomic_rmw_add_64_global
356 ; ARM32: dmb 359 ; ARM32: dmb
357 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 360 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
358 ; ARM32: adds 361 ; ARM32: adds
359 ; ARM32-NEXT: adc 362 ; ARM32-NEXT: adc
360 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 363 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
361 ; ARM32: bne 364 ; ARM32: bne
362 ; ARM32: dmb 365 ; ARM32: dmb
363 366
364 ; Test with some more register pressure. When we have an alloca, ebp is 367 ; Test with some more register pressure. When we have an alloca, ebp is
365 ; used to manage the stack frame, so it cannot be used as a register either. 368 ; used to manage the stack frame, so it cannot be used as a register either.
366 declare void @use_ptr(i32 %iptr) 369 declare void @use_ptr(i32 %iptr)
367 370
368 define i64 @test_atomic_rmw_add_64_alloca(i32 %iptr, i64 %v) { 371 define internal i64 @test_atomic_rmw_add_64_alloca(i32 %iptr, i64 %v) {
369 entry: 372 entry:
370 br label %eblock ; Disable alloca optimization 373 br label %eblock ; Disable alloca optimization
371 eblock: 374 eblock:
372 %alloca_ptr = alloca i8, i32 16, align 16 375 %alloca_ptr = alloca i8, i32 16, align 16
373 %ptr = inttoptr i32 %iptr to i64* 376 %ptr = inttoptr i32 %iptr to i64*
374 %old = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v, i32 6) 377 %old = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v, i32 6)
375 store i8 0, i8* %alloca_ptr, align 1 378 store i8 0, i8* %alloca_ptr, align 1
376 store i8 1, i8* %alloca_ptr, align 1 379 store i8 1, i8* %alloca_ptr, align 1
377 store i8 2, i8* %alloca_ptr, align 1 380 store i8 2, i8* %alloca_ptr, align 1
378 store i8 3, i8* %alloca_ptr, align 1 381 store i8 3, i8* %alloca_ptr, align 1
(...skipping 16 matching lines...) Expand all
395 ; CHECK: call {{.*}} R_{{.*}} use_ptr 398 ; CHECK: call {{.*}} R_{{.*}} use_ptr
396 ; ARM32-LABEL: test_atomic_rmw_add_64_alloca 399 ; ARM32-LABEL: test_atomic_rmw_add_64_alloca
397 ; ARM32: dmb 400 ; ARM32: dmb
398 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 401 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
399 ; ARM32: adds 402 ; ARM32: adds
400 ; ARM32-NEXT: adc 403 ; ARM32-NEXT: adc
401 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 404 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
402 ; ARM32: bne 405 ; ARM32: bne
403 ; ARM32: dmb 406 ; ARM32: dmb
404 407
405 define i32 @test_atomic_rmw_add_32_ignored(i32 %iptr, i32 %v) { 408 define internal i32 @test_atomic_rmw_add_32_ignored(i32 %iptr, i32 %v) {
406 entry: 409 entry:
407 %ptr = inttoptr i32 %iptr to i32* 410 %ptr = inttoptr i32 %iptr to i32*
408 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %ptr, i32 %v, i32 6) 411 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %ptr, i32 %v, i32 6)
409 ret i32 %v 412 ret i32 %v
410 } 413 }
411 ; Technically this could use "lock add" instead of "lock xadd", if liveness 414 ; Technically this could use "lock add" instead of "lock xadd", if liveness
412 ; tells us that the destination variable is dead. 415 ; tells us that the destination variable is dead.
413 ; CHECK-LABEL: test_atomic_rmw_add_32_ignored 416 ; CHECK-LABEL: test_atomic_rmw_add_32_ignored
414 ; CHECK: lock xadd DWORD {{.*}},[[REG:.*]] 417 ; CHECK: lock xadd DWORD {{.*}},[[REG:.*]]
415 ; ARM32-LABEL: test_atomic_rmw_add_32_ignored 418 ; ARM32-LABEL: test_atomic_rmw_add_32_ignored
416 ; ARM32: dmb 419 ; ARM32: dmb
417 ; ARM32: ldrex 420 ; ARM32: ldrex
418 ; ARM32: add 421 ; ARM32: add
419 ; ARM32: strex 422 ; ARM32: strex
420 ; ARM32: bne 423 ; ARM32: bne
421 ; ARM32: dmb 424 ; ARM32: dmb
422 425
423 ; Atomic RMW 64 needs to be expanded into its own loop. 426 ; Atomic RMW 64 needs to be expanded into its own loop.
424 ; Make sure that works w/ non-trivial function bodies. 427 ; Make sure that works w/ non-trivial function bodies.
425 define i64 @test_atomic_rmw_add_64_loop(i32 %iptr, i64 %v) { 428 define internal i64 @test_atomic_rmw_add_64_loop(i32 %iptr, i64 %v) {
426 entry: 429 entry:
427 %x = icmp ult i64 %v, 100 430 %x = icmp ult i64 %v, 100
428 br i1 %x, label %err, label %loop 431 br i1 %x, label %err, label %loop
429 432
430 loop: 433 loop:
431 %v_next = phi i64 [ %v, %entry ], [ %next, %loop ] 434 %v_next = phi i64 [ %v, %entry ], [ %next, %loop ]
432 %ptr = inttoptr i32 %iptr to i64* 435 %ptr = inttoptr i32 %iptr to i64*
433 %next = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v_next, i32 6) 436 %next = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v_next, i32 6)
434 %success = icmp eq i64 %next, 100 437 %success = icmp eq i64 %next, 100
435 br i1 %success, label %done, label %loop 438 br i1 %success, label %done, label %loop
(...skipping 19 matching lines...) Expand all
455 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 458 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
456 ; ARM32: adds 459 ; ARM32: adds
457 ; ARM32-NEXT: adc 460 ; ARM32-NEXT: adc
458 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 461 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
459 ; ARM32: bne 462 ; ARM32: bne
460 ; ARM32: dmb 463 ; ARM32: dmb
461 ; ARM32: b 464 ; ARM32: b
462 465
463 ;; sub 466 ;; sub
464 467
465 define i32 @test_atomic_rmw_sub_8(i32 %iptr, i32 %v) { 468 define internal i32 @test_atomic_rmw_sub_8(i32 %iptr, i32 %v) {
466 entry: 469 entry:
467 %trunc = trunc i32 %v to i8 470 %trunc = trunc i32 %v to i8
468 %ptr = inttoptr i32 %iptr to i8* 471 %ptr = inttoptr i32 %iptr to i8*
469 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 2, i8* %ptr, i8 %trunc, i32 6) 472 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 2, i8* %ptr, i8 %trunc, i32 6)
470 %a_ext = zext i8 %a to i32 473 %a_ext = zext i8 %a to i32
471 ret i32 %a_ext 474 ret i32 %a_ext
472 } 475 }
473 ; CHECK-LABEL: test_atomic_rmw_sub_8 476 ; CHECK-LABEL: test_atomic_rmw_sub_8
474 ; CHECK: neg [[REG:.*]] 477 ; CHECK: neg [[REG:.*]]
475 ; CHECK: lock xadd BYTE {{.*}},[[REG]] 478 ; CHECK: lock xadd BYTE {{.*}},[[REG]]
476 ; CHECK: {{mov|movzx}} {{.*}},[[REG]] 479 ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
477 ; ARM32-LABEL: test_atomic_rmw_sub_8 480 ; ARM32-LABEL: test_atomic_rmw_sub_8
478 ; ARM32: dmb 481 ; ARM32: dmb
479 ; ARM32: ldrexb 482 ; ARM32: ldrexb
480 ; ARM32: sub 483 ; ARM32: sub
481 ; ARM32: strexb 484 ; ARM32: strexb
482 ; ARM32: bne 485 ; ARM32: bne
483 ; ARM32: dmb 486 ; ARM32: dmb
484 487
485 define i32 @test_atomic_rmw_sub_16(i32 %iptr, i32 %v) { 488 define internal i32 @test_atomic_rmw_sub_16(i32 %iptr, i32 %v) {
486 entry: 489 entry:
487 %trunc = trunc i32 %v to i16 490 %trunc = trunc i32 %v to i16
488 %ptr = inttoptr i32 %iptr to i16* 491 %ptr = inttoptr i32 %iptr to i16*
489 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 2, i16* %ptr, i16 %trunc, i32 6) 492 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 2, i16* %ptr, i16 %trunc, i32 6)
490 %a_ext = zext i16 %a to i32 493 %a_ext = zext i16 %a to i32
491 ret i32 %a_ext 494 ret i32 %a_ext
492 } 495 }
493 ; CHECK-LABEL: test_atomic_rmw_sub_16 496 ; CHECK-LABEL: test_atomic_rmw_sub_16
494 ; CHECK: neg [[REG:.*]] 497 ; CHECK: neg [[REG:.*]]
495 ; CHECK: lock xadd WORD {{.*}},[[REG]] 498 ; CHECK: lock xadd WORD {{.*}},[[REG]]
496 ; CHECK: {{mov|movzx}} {{.*}},[[REG]] 499 ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
497 ; ARM32-LABEL: test_atomic_rmw_sub_16 500 ; ARM32-LABEL: test_atomic_rmw_sub_16
498 ; ARM32: dmb 501 ; ARM32: dmb
499 ; ARM32: ldrexh 502 ; ARM32: ldrexh
500 ; ARM32: sub 503 ; ARM32: sub
501 ; ARM32: strexh 504 ; ARM32: strexh
502 ; ARM32: bne 505 ; ARM32: bne
503 ; ARM32: dmb 506 ; ARM32: dmb
504 507
505 define i32 @test_atomic_rmw_sub_32(i32 %iptr, i32 %v) { 508 define internal i32 @test_atomic_rmw_sub_32(i32 %iptr, i32 %v) {
506 entry: 509 entry:
507 %ptr = inttoptr i32 %iptr to i32* 510 %ptr = inttoptr i32 %iptr to i32*
508 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 2, i32* %ptr, i32 %v, i32 6) 511 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 2, i32* %ptr, i32 %v, i32 6)
509 ret i32 %a 512 ret i32 %a
510 } 513 }
511 ; CHECK-LABEL: test_atomic_rmw_sub_32 514 ; CHECK-LABEL: test_atomic_rmw_sub_32
512 ; CHECK: neg [[REG:.*]] 515 ; CHECK: neg [[REG:.*]]
513 ; CHECK: lock xadd DWORD {{.*}},[[REG]] 516 ; CHECK: lock xadd DWORD {{.*}},[[REG]]
514 ; CHECK: mov {{.*}},[[REG]] 517 ; CHECK: mov {{.*}},[[REG]]
515 ; ARM32-LABEL: test_atomic_rmw_sub_32 518 ; ARM32-LABEL: test_atomic_rmw_sub_32
516 ; ARM32: dmb 519 ; ARM32: dmb
517 ; ARM32: ldrex 520 ; ARM32: ldrex
518 ; ARM32: sub 521 ; ARM32: sub
519 ; ARM32: strex 522 ; ARM32: strex
520 ; ARM32: bne 523 ; ARM32: bne
521 ; ARM32: dmb 524 ; ARM32: dmb
522 525
523 define i64 @test_atomic_rmw_sub_64(i32 %iptr, i64 %v) { 526 define internal i64 @test_atomic_rmw_sub_64(i32 %iptr, i64 %v) {
524 entry: 527 entry:
525 %ptr = inttoptr i32 %iptr to i64* 528 %ptr = inttoptr i32 %iptr to i64*
526 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 2, i64* %ptr, i64 %v, i32 6) 529 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 2, i64* %ptr, i64 %v, i32 6)
527 ret i64 %a 530 ret i64 %a
528 } 531 }
529 ; CHECK-LABEL: test_atomic_rmw_sub_64 532 ; CHECK-LABEL: test_atomic_rmw_sub_64
530 ; CHECK: push ebx 533 ; CHECK: push ebx
531 ; CHECK: mov eax,DWORD PTR [{{.*}}] 534 ; CHECK: mov eax,DWORD PTR [{{.*}}]
532 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4] 535 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
533 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax 536 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax
534 ; CHECK: sub ebx,{{.*e.[^x]}} 537 ; CHECK: sub ebx,{{.*e.[^x]}}
535 ; CHECK: mov ecx,edx 538 ; CHECK: mov ecx,edx
536 ; CHECK: sbb ecx,{{.*e.[^x]}} 539 ; CHECK: sbb ecx,{{.*e.[^x]}}
537 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}} 540 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
538 ; CHECK: jne [[LABEL]] 541 ; CHECK: jne [[LABEL]]
539 ; ARM32-LABEL: test_atomic_rmw_sub_64 542 ; ARM32-LABEL: test_atomic_rmw_sub_64
540 ; ARM32: dmb 543 ; ARM32: dmb
541 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 544 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
542 ; ARM32: subs 545 ; ARM32: subs
543 ; ARM32-NEXT: sbc 546 ; ARM32-NEXT: sbc
544 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 547 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
545 ; ARM32: bne 548 ; ARM32: bne
546 ; ARM32: dmb 549 ; ARM32: dmb
547 550
548 define i32 @test_atomic_rmw_sub_32_ignored(i32 %iptr, i32 %v) { 551 define internal i32 @test_atomic_rmw_sub_32_ignored(i32 %iptr, i32 %v) {
549 entry: 552 entry:
550 %ptr = inttoptr i32 %iptr to i32* 553 %ptr = inttoptr i32 %iptr to i32*
551 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 2, i32* %ptr, i32 %v, i32 6) 554 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 2, i32* %ptr, i32 %v, i32 6)
552 ret i32 %v 555 ret i32 %v
553 } 556 }
554 ; Could use "lock sub" instead of "neg; lock xadd" 557 ; Could use "lock sub" instead of "neg; lock xadd"
555 ; CHECK-LABEL: test_atomic_rmw_sub_32_ignored 558 ; CHECK-LABEL: test_atomic_rmw_sub_32_ignored
556 ; CHECK: neg [[REG:.*]] 559 ; CHECK: neg [[REG:.*]]
557 ; CHECK: lock xadd DWORD {{.*}},[[REG]] 560 ; CHECK: lock xadd DWORD {{.*}},[[REG]]
558 ; ARM32-LABEL: test_atomic_rmw_sub_32_ignored 561 ; ARM32-LABEL: test_atomic_rmw_sub_32_ignored
559 ; ARM32: dmb 562 ; ARM32: dmb
560 ; ARM32: ldrex 563 ; ARM32: ldrex
561 ; ARM32: sub 564 ; ARM32: sub
562 ; ARM32: strex 565 ; ARM32: strex
563 ; ARM32: bne 566 ; ARM32: bne
564 ; ARM32: dmb 567 ; ARM32: dmb
565 568
566 ;; or 569 ;; or
567 570
568 define i32 @test_atomic_rmw_or_8(i32 %iptr, i32 %v) { 571 define internal i32 @test_atomic_rmw_or_8(i32 %iptr, i32 %v) {
569 entry: 572 entry:
570 %trunc = trunc i32 %v to i8 573 %trunc = trunc i32 %v to i8
571 %ptr = inttoptr i32 %iptr to i8* 574 %ptr = inttoptr i32 %iptr to i8*
572 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 3, i8* %ptr, i8 %trunc, i32 6) 575 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 3, i8* %ptr, i8 %trunc, i32 6)
573 %a_ext = zext i8 %a to i32 576 %a_ext = zext i8 %a to i32
574 ret i32 %a_ext 577 ret i32 %a_ext
575 } 578 }
576 ; CHECK-LABEL: test_atomic_rmw_or_8 579 ; CHECK-LABEL: test_atomic_rmw_or_8
577 ; CHECK: mov al,BYTE PTR 580 ; CHECK: mov al,BYTE PTR
578 ; Dest cannot be eax here, because eax is used for the old value. Also want 581 ; Dest cannot be eax here, because eax is used for the old value. Also want
579 ; to make sure that cmpxchg's source is the same register. 582 ; to make sure that cmpxchg's source is the same register.
580 ; CHECK: or [[REG:[^a].]] 583 ; CHECK: or [[REG:[^a].]]
581 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]] 584 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]]
582 ; CHECK: jne 585 ; CHECK: jne
583 ; ARM32-LABEL: test_atomic_rmw_or_8 586 ; ARM32-LABEL: test_atomic_rmw_or_8
584 ; ARM32: dmb 587 ; ARM32: dmb
585 ; ARM32: ldrexb 588 ; ARM32: ldrexb
586 ; ARM32: orr 589 ; ARM32: orr
587 ; ARM32: strexb 590 ; ARM32: strexb
588 ; ARM32: bne 591 ; ARM32: bne
589 ; ARM32: dmb 592 ; ARM32: dmb
590 593
591 ; Same test as above, but with a global address to test FakeUse issues. 594 ; Same test as above, but with a global address to test FakeUse issues.
592 define i32 @test_atomic_rmw_or_8_global(i32 %v) { 595 define internal i32 @test_atomic_rmw_or_8_global(i32 %v) {
593 entry: 596 entry:
594 %trunc = trunc i32 %v to i8 597 %trunc = trunc i32 %v to i8
595 %ptr = bitcast [1 x i8]* @Global8 to i8* 598 %ptr = bitcast [1 x i8]* @Global8 to i8*
596 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 3, i8* %ptr, i8 %trunc, i32 6) 599 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 3, i8* %ptr, i8 %trunc, i32 6)
597 %a_ext = zext i8 %a to i32 600 %a_ext = zext i8 %a to i32
598 ret i32 %a_ext 601 ret i32 %a_ext
599 } 602 }
600 ; CHECK-LABEL: test_atomic_rmw_or_8_global 603 ; CHECK-LABEL: test_atomic_rmw_or_8_global
601 ; ARM32-LABEL: test_atomic_rmw_or_8_global 604 ; ARM32-LABEL: test_atomic_rmw_or_8_global
602 ; ARM32: movw [[PTR:r[0-9]+]], #:lower16:Global8 605 ; ARM32: movw [[PTR:r[0-9]+]], #:lower16:Global8
603 ; ARM32: movt [[PTR]], #:upper16:Global8 606 ; ARM32: movt [[PTR]], #:upper16:Global8
604 ; ARM32: dmb 607 ; ARM32: dmb
605 ; ARM32: ldrexb r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}} 608 ; ARM32: ldrexb r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
606 ; ARM32: orr 609 ; ARM32: orr
607 ; ARM32: strexb 610 ; ARM32: strexb
608 ; ARM32: bne 611 ; ARM32: bne
609 ; ARM32: dmb 612 ; ARM32: dmb
610 613
611 define i32 @test_atomic_rmw_or_16(i32 %iptr, i32 %v) { 614 define internal i32 @test_atomic_rmw_or_16(i32 %iptr, i32 %v) {
612 entry: 615 entry:
613 %trunc = trunc i32 %v to i16 616 %trunc = trunc i32 %v to i16
614 %ptr = inttoptr i32 %iptr to i16* 617 %ptr = inttoptr i32 %iptr to i16*
615 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 3, i16* %ptr, i16 %trunc, i32 6) 618 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 3, i16* %ptr, i16 %trunc, i32 6)
616 %a_ext = zext i16 %a to i32 619 %a_ext = zext i16 %a to i32
617 ret i32 %a_ext 620 ret i32 %a_ext
618 } 621 }
619 ; CHECK-LABEL: test_atomic_rmw_or_16 622 ; CHECK-LABEL: test_atomic_rmw_or_16
620 ; CHECK: mov ax,WORD PTR 623 ; CHECK: mov ax,WORD PTR
621 ; CHECK: or [[REG:[^a].]] 624 ; CHECK: or [[REG:[^a].]]
622 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}],[[REG]] 625 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}],[[REG]]
623 ; CHECK: jne 626 ; CHECK: jne
624 ; ARM32-LABEL: test_atomic_rmw_or_16 627 ; ARM32-LABEL: test_atomic_rmw_or_16
625 ; ARM32: dmb 628 ; ARM32: dmb
626 ; ARM32: ldrexh 629 ; ARM32: ldrexh
627 ; ARM32: orr 630 ; ARM32: orr
628 ; ARM32: strexh 631 ; ARM32: strexh
629 ; ARM32: bne 632 ; ARM32: bne
630 ; ARM32: dmb 633 ; ARM32: dmb
631 634
632 ; Same test as above, but with a global address to test FakeUse issues. 635 ; Same test as above, but with a global address to test FakeUse issues.
633 define i32 @test_atomic_rmw_or_16_global(i32 %v) { 636 define internal i32 @test_atomic_rmw_or_16_global(i32 %v) {
634 entry: 637 entry:
635 %trunc = trunc i32 %v to i16 638 %trunc = trunc i32 %v to i16
636 %ptr = bitcast [2 x i8]* @Global16 to i16* 639 %ptr = bitcast [2 x i8]* @Global16 to i16*
637 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 3, i16* %ptr, i16 %trunc, i32 6) 640 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 3, i16* %ptr, i16 %trunc, i32 6)
638 %a_ext = zext i16 %a to i32 641 %a_ext = zext i16 %a to i32
639 ret i32 %a_ext 642 ret i32 %a_ext
640 } 643 }
641 ; CHECK-LABEL: test_atomic_rmw_or_16_global 644 ; CHECK-LABEL: test_atomic_rmw_or_16_global
642 ; ARM32-LABEL: test_atomic_rmw_or_16_global 645 ; ARM32-LABEL: test_atomic_rmw_or_16_global
643 ; ARM32: movw [[PTR:r[0-9]+]], #:lower16:Global16 646 ; ARM32: movw [[PTR:r[0-9]+]], #:lower16:Global16
644 ; ARM32: movt [[PTR]], #:upper16:Global16 647 ; ARM32: movt [[PTR]], #:upper16:Global16
645 ; ARM32: dmb 648 ; ARM32: dmb
646 ; ARM32: ldrexh r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}} 649 ; ARM32: ldrexh r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
647 ; ARM32: orr 650 ; ARM32: orr
648 ; ARM32: strexh 651 ; ARM32: strexh
649 ; ARM32: bne 652 ; ARM32: bne
650 ; ARM32: dmb 653 ; ARM32: dmb
651 654
652 define i32 @test_atomic_rmw_or_32(i32 %iptr, i32 %v) { 655 define internal i32 @test_atomic_rmw_or_32(i32 %iptr, i32 %v) {
653 entry: 656 entry:
654 %ptr = inttoptr i32 %iptr to i32* 657 %ptr = inttoptr i32 %iptr to i32*
655 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 3, i32* %ptr, i32 %v, i32 6) 658 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 3, i32* %ptr, i32 %v, i32 6)
656 ret i32 %a 659 ret i32 %a
657 } 660 }
658 ; CHECK-LABEL: test_atomic_rmw_or_32 661 ; CHECK-LABEL: test_atomic_rmw_or_32
659 ; CHECK: mov eax,DWORD PTR 662 ; CHECK: mov eax,DWORD PTR
660 ; CHECK: or [[REG:e[^a].]] 663 ; CHECK: or [[REG:e[^a].]]
661 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],[[REG]] 664 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],[[REG]]
662 ; CHECK: jne 665 ; CHECK: jne
663 ; ARM32-LABEL: test_atomic_rmw_or_32 666 ; ARM32-LABEL: test_atomic_rmw_or_32
664 ; ARM32: dmb 667 ; ARM32: dmb
665 ; ARM32: ldrex 668 ; ARM32: ldrex
666 ; ARM32: orr 669 ; ARM32: orr
667 ; ARM32: strex 670 ; ARM32: strex
668 ; ARM32: bne 671 ; ARM32: bne
669 ; ARM32: dmb 672 ; ARM32: dmb
670 673
671 ; Same test as above, but with a global address to test FakeUse issues. 674 ; Same test as above, but with a global address to test FakeUse issues.
672 define i32 @test_atomic_rmw_or_32_global(i32 %v) { 675 define internal i32 @test_atomic_rmw_or_32_global(i32 %v) {
673 entry: 676 entry:
674 %ptr = bitcast [4 x i8]* @Global32 to i32* 677 %ptr = bitcast [4 x i8]* @Global32 to i32*
675 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 3, i32* %ptr, i32 %v, i32 6) 678 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 3, i32* %ptr, i32 %v, i32 6)
676 ret i32 %a 679 ret i32 %a
677 } 680 }
678 ; CHECK-LABEL: test_atomic_rmw_or_32_global 681 ; CHECK-LABEL: test_atomic_rmw_or_32_global
679 ; ARM32-LABEL: test_atomic_rmw_or_32_global 682 ; ARM32-LABEL: test_atomic_rmw_or_32_global
680 ; ARM32: movw [[PTR:r[0-9]+]], #:lower16:Global32 683 ; ARM32: movw [[PTR:r[0-9]+]], #:lower16:Global32
681 ; ARM32: movt [[PTR]], #:upper16:Global32 684 ; ARM32: movt [[PTR]], #:upper16:Global32
682 ; ARM32: dmb 685 ; ARM32: dmb
683 ; ARM32: ldrex r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}} 686 ; ARM32: ldrex r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
684 ; ARM32: orr 687 ; ARM32: orr
685 ; ARM32: strex 688 ; ARM32: strex
686 ; ARM32: bne 689 ; ARM32: bne
687 ; ARM32: dmb 690 ; ARM32: dmb
688 691
689 define i64 @test_atomic_rmw_or_64(i32 %iptr, i64 %v) { 692 define internal i64 @test_atomic_rmw_or_64(i32 %iptr, i64 %v) {
690 entry: 693 entry:
691 %ptr = inttoptr i32 %iptr to i64* 694 %ptr = inttoptr i32 %iptr to i64*
692 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 3, i64* %ptr, i64 %v, i32 6) 695 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 3, i64* %ptr, i64 %v, i32 6)
693 ret i64 %a 696 ret i64 %a
694 } 697 }
695 ; CHECK-LABEL: test_atomic_rmw_or_64 698 ; CHECK-LABEL: test_atomic_rmw_or_64
696 ; CHECK: push ebx 699 ; CHECK: push ebx
697 ; CHECK: mov eax,DWORD PTR [{{.*}}] 700 ; CHECK: mov eax,DWORD PTR [{{.*}}]
698 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4] 701 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
699 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax 702 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax
700 ; CHECK: or ebx,{{.*e.[^x]}} 703 ; CHECK: or ebx,{{.*e.[^x]}}
701 ; CHECK: mov ecx,edx 704 ; CHECK: mov ecx,edx
702 ; CHECK: or ecx,{{.*e.[^x]}} 705 ; CHECK: or ecx,{{.*e.[^x]}}
703 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}} 706 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
704 ; CHECK: jne [[LABEL]] 707 ; CHECK: jne [[LABEL]]
705 ; ARM32-LABEL: test_atomic_rmw_or_64 708 ; ARM32-LABEL: test_atomic_rmw_or_64
706 ; ARM32: dmb 709 ; ARM32: dmb
707 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 710 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
708 ; ARM32: orr 711 ; ARM32: orr
709 ; ARM32-NEXT: orr 712 ; ARM32-NEXT: orr
710 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 713 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
711 ; ARM32: bne 714 ; ARM32: bne
712 ; ARM32: dmb 715 ; ARM32: dmb
713 716
714 define i32 @test_atomic_rmw_or_32_ignored(i32 %iptr, i32 %v) { 717 define internal i32 @test_atomic_rmw_or_32_ignored(i32 %iptr, i32 %v) {
715 entry: 718 entry:
716 %ptr = inttoptr i32 %iptr to i32* 719 %ptr = inttoptr i32 %iptr to i32*
717 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 3, i32* %ptr, i32 %v, i32 6) 720 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 3, i32* %ptr, i32 %v, i32 6)
718 ret i32 %v 721 ret i32 %v
719 } 722 }
720 ; CHECK-LABEL: test_atomic_rmw_or_32_ignored 723 ; CHECK-LABEL: test_atomic_rmw_or_32_ignored
721 ; Could just "lock or", if we inspect the liveness information first. 724 ; Could just "lock or", if we inspect the liveness information first.
722 ; Would also need a way to introduce "lock"'edness to binary 725 ; Would also need a way to introduce "lock"'edness to binary
723 ; operators without introducing overhead on the more common binary ops. 726 ; operators without introducing overhead on the more common binary ops.
724 ; CHECK: mov eax,DWORD PTR 727 ; CHECK: mov eax,DWORD PTR
725 ; CHECK: or [[REG:e[^a].]] 728 ; CHECK: or [[REG:e[^a].]]
726 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],[[REG]] 729 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],[[REG]]
727 ; CHECK: jne 730 ; CHECK: jne
728 ; ARM32-LABEL: test_atomic_rmw_or_32_ignored 731 ; ARM32-LABEL: test_atomic_rmw_or_32_ignored
729 ; ARM32: dmb 732 ; ARM32: dmb
730 ; ARM32: ldrex 733 ; ARM32: ldrex
731 ; ARM32: orr 734 ; ARM32: orr
732 ; ARM32: strex 735 ; ARM32: strex
733 ; ARM32: bne 736 ; ARM32: bne
734 ; ARM32: dmb 737 ; ARM32: dmb
735 738
736 ;; and 739 ;; and
737 740
738 define i32 @test_atomic_rmw_and_8(i32 %iptr, i32 %v) { 741 define internal i32 @test_atomic_rmw_and_8(i32 %iptr, i32 %v) {
739 entry: 742 entry:
740 %trunc = trunc i32 %v to i8 743 %trunc = trunc i32 %v to i8
741 %ptr = inttoptr i32 %iptr to i8* 744 %ptr = inttoptr i32 %iptr to i8*
742 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 4, i8* %ptr, i8 %trunc, i32 6) 745 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 4, i8* %ptr, i8 %trunc, i32 6)
743 %a_ext = zext i8 %a to i32 746 %a_ext = zext i8 %a to i32
744 ret i32 %a_ext 747 ret i32 %a_ext
745 } 748 }
746 ; CHECK-LABEL: test_atomic_rmw_and_8 749 ; CHECK-LABEL: test_atomic_rmw_and_8
747 ; CHECK: mov al,BYTE PTR 750 ; CHECK: mov al,BYTE PTR
748 ; CHECK: and [[REG:[^a].]] 751 ; CHECK: and [[REG:[^a].]]
749 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]] 752 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]]
750 ; CHECK: jne 753 ; CHECK: jne
751 ; ARM32-LABEL: test_atomic_rmw_and_8 754 ; ARM32-LABEL: test_atomic_rmw_and_8
752 ; ARM32: dmb 755 ; ARM32: dmb
753 ; ARM32: ldrexb 756 ; ARM32: ldrexb
754 ; ARM32: and 757 ; ARM32: and
755 ; ARM32: strexb 758 ; ARM32: strexb
756 ; ARM32: bne 759 ; ARM32: bne
757 ; ARM32: dmb 760 ; ARM32: dmb
758 761
759 define i32 @test_atomic_rmw_and_16(i32 %iptr, i32 %v) { 762 define internal i32 @test_atomic_rmw_and_16(i32 %iptr, i32 %v) {
760 entry: 763 entry:
761 %trunc = trunc i32 %v to i16 764 %trunc = trunc i32 %v to i16
762 %ptr = inttoptr i32 %iptr to i16* 765 %ptr = inttoptr i32 %iptr to i16*
763 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 4, i16* %ptr, i16 %trunc, i32 6) 766 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 4, i16* %ptr, i16 %trunc, i32 6)
764 %a_ext = zext i16 %a to i32 767 %a_ext = zext i16 %a to i32
765 ret i32 %a_ext 768 ret i32 %a_ext
766 } 769 }
767 ; CHECK-LABEL: test_atomic_rmw_and_16 770 ; CHECK-LABEL: test_atomic_rmw_and_16
768 ; CHECK: mov ax,WORD PTR 771 ; CHECK: mov ax,WORD PTR
769 ; CHECK: and 772 ; CHECK: and
770 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}] 773 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}]
771 ; CHECK: jne 774 ; CHECK: jne
772 ; ARM32-LABEL: test_atomic_rmw_and_16 775 ; ARM32-LABEL: test_atomic_rmw_and_16
773 ; ARM32: dmb 776 ; ARM32: dmb
774 ; ARM32: ldrexh 777 ; ARM32: ldrexh
775 ; ARM32: and 778 ; ARM32: and
776 ; ARM32: strexh 779 ; ARM32: strexh
777 ; ARM32: bne 780 ; ARM32: bne
778 ; ARM32: dmb 781 ; ARM32: dmb
779 782
780 define i32 @test_atomic_rmw_and_32(i32 %iptr, i32 %v) { 783 define internal i32 @test_atomic_rmw_and_32(i32 %iptr, i32 %v) {
781 entry: 784 entry:
782 %ptr = inttoptr i32 %iptr to i32* 785 %ptr = inttoptr i32 %iptr to i32*
783 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 4, i32* %ptr, i32 %v, i32 6) 786 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 4, i32* %ptr, i32 %v, i32 6)
784 ret i32 %a 787 ret i32 %a
785 } 788 }
786 ; CHECK-LABEL: test_atomic_rmw_and_32 789 ; CHECK-LABEL: test_atomic_rmw_and_32
787 ; CHECK: mov eax,DWORD PTR 790 ; CHECK: mov eax,DWORD PTR
788 ; CHECK: and 791 ; CHECK: and
789 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}] 792 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
790 ; CHECK: jne 793 ; CHECK: jne
791 ; ARM32-LABEL: test_atomic_rmw_and_32 794 ; ARM32-LABEL: test_atomic_rmw_and_32
792 ; ARM32: dmb 795 ; ARM32: dmb
793 ; ARM32: ldrex 796 ; ARM32: ldrex
794 ; ARM32: and 797 ; ARM32: and
795 ; ARM32: strex 798 ; ARM32: strex
796 ; ARM32: bne 799 ; ARM32: bne
797 ; ARM32: dmb 800 ; ARM32: dmb
798 801
799 define i64 @test_atomic_rmw_and_64(i32 %iptr, i64 %v) { 802 define internal i64 @test_atomic_rmw_and_64(i32 %iptr, i64 %v) {
800 entry: 803 entry:
801 %ptr = inttoptr i32 %iptr to i64* 804 %ptr = inttoptr i32 %iptr to i64*
802 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 4, i64* %ptr, i64 %v, i32 6) 805 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 4, i64* %ptr, i64 %v, i32 6)
803 ret i64 %a 806 ret i64 %a
804 } 807 }
805 ; CHECK-LABEL: test_atomic_rmw_and_64 808 ; CHECK-LABEL: test_atomic_rmw_and_64
806 ; CHECK: push ebx 809 ; CHECK: push ebx
807 ; CHECK: mov eax,DWORD PTR [{{.*}}] 810 ; CHECK: mov eax,DWORD PTR [{{.*}}]
808 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4] 811 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
809 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax 812 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax
810 ; CHECK: and ebx,{{.*e.[^x]}} 813 ; CHECK: and ebx,{{.*e.[^x]}}
811 ; CHECK: mov ecx,edx 814 ; CHECK: mov ecx,edx
812 ; CHECK: and ecx,{{.*e.[^x]}} 815 ; CHECK: and ecx,{{.*e.[^x]}}
813 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}} 816 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
814 ; CHECK: jne [[LABEL]] 817 ; CHECK: jne [[LABEL]]
815 ; ARM32-LABEL: test_atomic_rmw_and_64 818 ; ARM32-LABEL: test_atomic_rmw_and_64
816 ; ARM32: dmb 819 ; ARM32: dmb
817 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 820 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
818 ; ARM32: and 821 ; ARM32: and
819 ; ARM32-NEXT: and 822 ; ARM32-NEXT: and
820 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 823 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
821 ; ARM32: bne 824 ; ARM32: bne
822 ; ARM32: dmb 825 ; ARM32: dmb
823 826
824 define i32 @test_atomic_rmw_and_32_ignored(i32 %iptr, i32 %v) { 827 define internal i32 @test_atomic_rmw_and_32_ignored(i32 %iptr, i32 %v) {
825 entry: 828 entry:
826 %ptr = inttoptr i32 %iptr to i32* 829 %ptr = inttoptr i32 %iptr to i32*
827 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 4, i32* %ptr, i32 %v, i32 6) 830 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 4, i32* %ptr, i32 %v, i32 6)
828 ret i32 %v 831 ret i32 %v
829 } 832 }
830 ; CHECK-LABEL: test_atomic_rmw_and_32_ignored 833 ; CHECK-LABEL: test_atomic_rmw_and_32_ignored
831 ; Could just "lock and" 834 ; Could just "lock and"
832 ; CHECK: mov eax,DWORD PTR 835 ; CHECK: mov eax,DWORD PTR
833 ; CHECK: and 836 ; CHECK: and
834 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}] 837 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
835 ; CHECK: jne 838 ; CHECK: jne
836 ; ARM32-LABEL: test_atomic_rmw_and_32_ignored 839 ; ARM32-LABEL: test_atomic_rmw_and_32_ignored
837 ; ARM32: dmb 840 ; ARM32: dmb
838 ; ARM32: ldrex 841 ; ARM32: ldrex
839 ; ARM32: and 842 ; ARM32: and
840 ; ARM32: strex 843 ; ARM32: strex
841 ; ARM32: bne 844 ; ARM32: bne
842 ; ARM32: dmb 845 ; ARM32: dmb
843 846
844 ;; xor 847 ;; xor
845 848
846 define i32 @test_atomic_rmw_xor_8(i32 %iptr, i32 %v) { 849 define internal i32 @test_atomic_rmw_xor_8(i32 %iptr, i32 %v) {
847 entry: 850 entry:
848 %trunc = trunc i32 %v to i8 851 %trunc = trunc i32 %v to i8
849 %ptr = inttoptr i32 %iptr to i8* 852 %ptr = inttoptr i32 %iptr to i8*
850 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 5, i8* %ptr, i8 %trunc, i32 6) 853 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 5, i8* %ptr, i8 %trunc, i32 6)
851 %a_ext = zext i8 %a to i32 854 %a_ext = zext i8 %a to i32
852 ret i32 %a_ext 855 ret i32 %a_ext
853 } 856 }
854 ; CHECK-LABEL: test_atomic_rmw_xor_8 857 ; CHECK-LABEL: test_atomic_rmw_xor_8
855 ; CHECK: mov al,BYTE PTR 858 ; CHECK: mov al,BYTE PTR
856 ; CHECK: xor [[REG:[^a].]] 859 ; CHECK: xor [[REG:[^a].]]
857 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]] 860 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]]
858 ; CHECK: jne 861 ; CHECK: jne
859 ; ARM32-LABEL: test_atomic_rmw_xor_8 862 ; ARM32-LABEL: test_atomic_rmw_xor_8
860 ; ARM32: dmb 863 ; ARM32: dmb
861 ; ARM32: ldrexb 864 ; ARM32: ldrexb
862 ; ARM32: eor 865 ; ARM32: eor
863 ; ARM32: strexb 866 ; ARM32: strexb
864 ; ARM32: bne 867 ; ARM32: bne
865 ; ARM32: dmb 868 ; ARM32: dmb
866 869
867 define i32 @test_atomic_rmw_xor_16(i32 %iptr, i32 %v) { 870 define internal i32 @test_atomic_rmw_xor_16(i32 %iptr, i32 %v) {
868 entry: 871 entry:
869 %trunc = trunc i32 %v to i16 872 %trunc = trunc i32 %v to i16
870 %ptr = inttoptr i32 %iptr to i16* 873 %ptr = inttoptr i32 %iptr to i16*
871 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 5, i16* %ptr, i16 %trunc, i32 6) 874 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 5, i16* %ptr, i16 %trunc, i32 6)
872 %a_ext = zext i16 %a to i32 875 %a_ext = zext i16 %a to i32
873 ret i32 %a_ext 876 ret i32 %a_ext
874 } 877 }
875 ; CHECK-LABEL: test_atomic_rmw_xor_16 878 ; CHECK-LABEL: test_atomic_rmw_xor_16
876 ; CHECK: mov ax,WORD PTR 879 ; CHECK: mov ax,WORD PTR
877 ; CHECK: xor 880 ; CHECK: xor
878 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}] 881 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}]
879 ; CHECK: jne 882 ; CHECK: jne
880 ; ARM32-LABEL: test_atomic_rmw_xor_16 883 ; ARM32-LABEL: test_atomic_rmw_xor_16
881 ; ARM32: dmb 884 ; ARM32: dmb
882 ; ARM32: ldrexh 885 ; ARM32: ldrexh
883 ; ARM32: eor 886 ; ARM32: eor
884 ; ARM32: strexh 887 ; ARM32: strexh
885 ; ARM32: bne 888 ; ARM32: bne
886 ; ARM32: dmb 889 ; ARM32: dmb
887 890
888 define i32 @test_atomic_rmw_xor_32(i32 %iptr, i32 %v) { 891 define internal i32 @test_atomic_rmw_xor_32(i32 %iptr, i32 %v) {
889 entry: 892 entry:
890 %ptr = inttoptr i32 %iptr to i32* 893 %ptr = inttoptr i32 %iptr to i32*
891 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 5, i32* %ptr, i32 %v, i32 6) 894 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 5, i32* %ptr, i32 %v, i32 6)
892 ret i32 %a 895 ret i32 %a
893 } 896 }
894 ; CHECK-LABEL: test_atomic_rmw_xor_32 897 ; CHECK-LABEL: test_atomic_rmw_xor_32
895 ; CHECK: mov eax,DWORD PTR 898 ; CHECK: mov eax,DWORD PTR
896 ; CHECK: xor 899 ; CHECK: xor
897 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}] 900 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
898 ; CHECK: jne 901 ; CHECK: jne
899 ; ARM32-LABEL: test_atomic_rmw_xor_32 902 ; ARM32-LABEL: test_atomic_rmw_xor_32
900 ; ARM32: dmb 903 ; ARM32: dmb
901 ; ARM32: ldrex 904 ; ARM32: ldrex
902 ; ARM32: eor 905 ; ARM32: eor
903 ; ARM32: strex 906 ; ARM32: strex
904 ; ARM32: bne 907 ; ARM32: bne
905 ; ARM32: dmb 908 ; ARM32: dmb
906 909
907 define i64 @test_atomic_rmw_xor_64(i32 %iptr, i64 %v) { 910 define internal i64 @test_atomic_rmw_xor_64(i32 %iptr, i64 %v) {
908 entry: 911 entry:
909 %ptr = inttoptr i32 %iptr to i64* 912 %ptr = inttoptr i32 %iptr to i64*
910 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 5, i64* %ptr, i64 %v, i32 6) 913 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 5, i64* %ptr, i64 %v, i32 6)
911 ret i64 %a 914 ret i64 %a
912 } 915 }
913 ; CHECK-LABEL: test_atomic_rmw_xor_64 916 ; CHECK-LABEL: test_atomic_rmw_xor_64
914 ; CHECK: push ebx 917 ; CHECK: push ebx
915 ; CHECK: mov eax,DWORD PTR [{{.*}}] 918 ; CHECK: mov eax,DWORD PTR [{{.*}}]
916 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4] 919 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
917 ; CHECK: mov ebx,eax 920 ; CHECK: mov ebx,eax
918 ; CHECK: or ebx,{{.*e.[^x]}} 921 ; CHECK: or ebx,{{.*e.[^x]}}
919 ; CHECK: mov ecx,edx 922 ; CHECK: mov ecx,edx
920 ; CHECK: or ecx,{{.*e.[^x]}} 923 ; CHECK: or ecx,{{.*e.[^x]}}
921 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}} 924 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
922 ; CHECK: jne 925 ; CHECK: jne
923 ; ARM32-LABEL: test_atomic_rmw_xor_64 926 ; ARM32-LABEL: test_atomic_rmw_xor_64
924 ; ARM32: dmb 927 ; ARM32: dmb
925 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 928 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
926 ; ARM32: eor 929 ; ARM32: eor
927 ; ARM32-NEXT: eor 930 ; ARM32-NEXT: eor
928 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}] 931 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
929 ; ARM32: bne 932 ; ARM32: bne
930 ; ARM32: dmb 933 ; ARM32: dmb
931 934
932 define i32 @test_atomic_rmw_xor_32_ignored(i32 %iptr, i32 %v) { 935 define internal i32 @test_atomic_rmw_xor_32_ignored(i32 %iptr, i32 %v) {
933 entry: 936 entry:
934 %ptr = inttoptr i32 %iptr to i32* 937 %ptr = inttoptr i32 %iptr to i32*
935 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 5, i32* %ptr, i32 %v, i32 6) 938 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 5, i32* %ptr, i32 %v, i32 6)
936 ret i32 %v 939 ret i32 %v
937 } 940 }
938 ; CHECK-LABEL: test_atomic_rmw_xor_32_ignored 941 ; CHECK-LABEL: test_atomic_rmw_xor_32_ignored
939 ; CHECK: mov eax,DWORD PTR 942 ; CHECK: mov eax,DWORD PTR
940 ; CHECK: xor 943 ; CHECK: xor
941 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}] 944 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
942 ; CHECK: jne 945 ; CHECK: jne
943 ; ARM32-LABEL: test_atomic_rmw_xor_32_ignored 946 ; ARM32-LABEL: test_atomic_rmw_xor_32_ignored
944 ; ARM32: dmb 947 ; ARM32: dmb
945 ; ARM32: ldrex 948 ; ARM32: ldrex
946 ; ARM32: eor 949 ; ARM32: eor
947 ; ARM32: strex 950 ; ARM32: strex
948 ; ARM32: bne 951 ; ARM32: bne
949 ; ARM32: dmb 952 ; ARM32: dmb
950 953
951 ;; exchange 954 ;; exchange
952 955
953 define i32 @test_atomic_rmw_xchg_8(i32 %iptr, i32 %v) { 956 define internal i32 @test_atomic_rmw_xchg_8(i32 %iptr, i32 %v) {
954 entry: 957 entry:
955 %trunc = trunc i32 %v to i8 958 %trunc = trunc i32 %v to i8
956 %ptr = inttoptr i32 %iptr to i8* 959 %ptr = inttoptr i32 %iptr to i8*
957 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 6, i8* %ptr, i8 %trunc, i32 6) 960 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 6, i8* %ptr, i8 %trunc, i32 6)
958 %a_ext = zext i8 %a to i32 961 %a_ext = zext i8 %a to i32
959 ret i32 %a_ext 962 ret i32 %a_ext
960 } 963 }
961 ; CHECK-LABEL: test_atomic_rmw_xchg_8 964 ; CHECK-LABEL: test_atomic_rmw_xchg_8
962 ; CHECK: xchg BYTE PTR {{.*}},[[REG:.*]] 965 ; CHECK: xchg BYTE PTR {{.*}},[[REG:.*]]
963 ; ARM32-LABEL: test_atomic_rmw_xchg_8 966 ; ARM32-LABEL: test_atomic_rmw_xchg_8
964 ; ARM32: dmb 967 ; ARM32: dmb
965 ; ARM32: ldrexb 968 ; ARM32: ldrexb
966 ; ARM32: strexb 969 ; ARM32: strexb
967 ; ARM32: cmp 970 ; ARM32: cmp
968 ; ARM32: bne 971 ; ARM32: bne
969 ; ARM32: dmb 972 ; ARM32: dmb
970 973
971 define i32 @test_atomic_rmw_xchg_16(i32 %iptr, i32 %v) { 974 define internal i32 @test_atomic_rmw_xchg_16(i32 %iptr, i32 %v) {
972 entry: 975 entry:
973 %trunc = trunc i32 %v to i16 976 %trunc = trunc i32 %v to i16
974 %ptr = inttoptr i32 %iptr to i16* 977 %ptr = inttoptr i32 %iptr to i16*
975 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 6, i16* %ptr, i16 %trunc, i32 6) 978 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 6, i16* %ptr, i16 %trunc, i32 6)
976 %a_ext = zext i16 %a to i32 979 %a_ext = zext i16 %a to i32
977 ret i32 %a_ext 980 ret i32 %a_ext
978 } 981 }
979 ; CHECK-LABEL: test_atomic_rmw_xchg_16 982 ; CHECK-LABEL: test_atomic_rmw_xchg_16
980 ; CHECK: xchg WORD PTR {{.*}},[[REG:.*]] 983 ; CHECK: xchg WORD PTR {{.*}},[[REG:.*]]
981 ; ARM32-LABEL: test_atomic_rmw_xchg_16 984 ; ARM32-LABEL: test_atomic_rmw_xchg_16
982 ; ARM32: dmb 985 ; ARM32: dmb
983 ; ARM32: ldrexh 986 ; ARM32: ldrexh
984 ; ARM32: strexh 987 ; ARM32: strexh
985 ; ARM32: cmp 988 ; ARM32: cmp
986 ; ARM32: bne 989 ; ARM32: bne
987 ; ARM32: dmb 990 ; ARM32: dmb
988 991
989 define i32 @test_atomic_rmw_xchg_32(i32 %iptr, i32 %v) { 992 define internal i32 @test_atomic_rmw_xchg_32(i32 %iptr, i32 %v) {
990 entry: 993 entry:
991 %ptr = inttoptr i32 %iptr to i32* 994 %ptr = inttoptr i32 %iptr to i32*
992 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 6, i32* %ptr, i32 %v, i32 6) 995 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 6, i32* %ptr, i32 %v, i32 6)
993 ret i32 %a 996 ret i32 %a
994 } 997 }
995 ; CHECK-LABEL: test_atomic_rmw_xchg_32 998 ; CHECK-LABEL: test_atomic_rmw_xchg_32
996 ; CHECK: xchg DWORD PTR {{.*}},[[REG:.*]] 999 ; CHECK: xchg DWORD PTR {{.*}},[[REG:.*]]
997 ; ARM32-LABEL: test_atomic_rmw_xchg_32 1000 ; ARM32-LABEL: test_atomic_rmw_xchg_32
998 ; ARM32: dmb 1001 ; ARM32: dmb
999 ; ARM32: ldrex 1002 ; ARM32: ldrex
1000 ; ARM32: strex 1003 ; ARM32: strex
1001 ; ARM32: cmp 1004 ; ARM32: cmp
1002 ; ARM32: bne 1005 ; ARM32: bne
1003 ; ARM32: dmb 1006 ; ARM32: dmb
1004 1007
1005 define i64 @test_atomic_rmw_xchg_64(i32 %iptr, i64 %v) { 1008 define internal i64 @test_atomic_rmw_xchg_64(i32 %iptr, i64 %v) {
1006 entry: 1009 entry:
1007 %ptr = inttoptr i32 %iptr to i64* 1010 %ptr = inttoptr i32 %iptr to i64*
1008 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 6, i64* %ptr, i64 %v, i32 6) 1011 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 6, i64* %ptr, i64 %v, i32 6)
1009 ret i64 %a 1012 ret i64 %a
1010 } 1013 }
1011 ; CHECK-LABEL: test_atomic_rmw_xchg_64 1014 ; CHECK-LABEL: test_atomic_rmw_xchg_64
1012 ; CHECK: push ebx 1015 ; CHECK: push ebx
1013 ; CHECK-DAG: mov edx 1016 ; CHECK-DAG: mov edx
1014 ; CHECK-DAG: mov eax 1017 ; CHECK-DAG: mov eax
1015 ; CHECK-DAG: mov ecx 1018 ; CHECK-DAG: mov ecx
1016 ; CHECK-DAG: mov ebx 1019 ; CHECK-DAG: mov ebx
1017 ; CHECK: lock cmpxchg8b QWORD PTR [{{e.[^x]}} 1020 ; CHECK: lock cmpxchg8b QWORD PTR [{{e.[^x]}}
1018 ; CHECK: jne 1021 ; CHECK: jne
1019 ; ARM32-LABEL: test_atomic_rmw_xchg_64 1022 ; ARM32-LABEL: test_atomic_rmw_xchg_64
1020 ; ARM32: dmb 1023 ; ARM32: dmb
1021 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}} 1024 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
1022 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}} 1025 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
1023 ; ARM32: cmp 1026 ; ARM32: cmp
1024 ; ARM32: bne 1027 ; ARM32: bne
1025 ; ARM32: dmb 1028 ; ARM32: dmb
1026 1029
1027 define i32 @test_atomic_rmw_xchg_32_ignored(i32 %iptr, i32 %v) { 1030 define internal i32 @test_atomic_rmw_xchg_32_ignored(i32 %iptr, i32 %v) {
1028 entry: 1031 entry:
1029 %ptr = inttoptr i32 %iptr to i32* 1032 %ptr = inttoptr i32 %iptr to i32*
1030 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 6, i32* %ptr, i32 %v, i32 6) 1033 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 6, i32* %ptr, i32 %v, i32 6)
1031 ret i32 %v 1034 ret i32 %v
1032 } 1035 }
1033 ; In this case, ignoring the return value doesn't help. The xchg is 1036 ; In this case, ignoring the return value doesn't help. The xchg is
1034 ; used to do an atomic store. 1037 ; used to do an atomic store.
1035 ; CHECK-LABEL: test_atomic_rmw_xchg_32_ignored 1038 ; CHECK-LABEL: test_atomic_rmw_xchg_32_ignored
1036 ; CHECK: xchg DWORD PTR {{.*}},[[REG:.*]] 1039 ; CHECK: xchg DWORD PTR {{.*}},[[REG:.*]]
1037 ; ARM32-LABEL: test_atomic_rmw_xchg_32_ignored 1040 ; ARM32-LABEL: test_atomic_rmw_xchg_32_ignored
1038 ; ARM32: dmb 1041 ; ARM32: dmb
1039 ; ARM32: ldrex 1042 ; ARM32: ldrex
1040 ; ARM32: strex 1043 ; ARM32: strex
1041 ; ARM32: cmp 1044 ; ARM32: cmp
1042 ; ARM32: bne 1045 ; ARM32: bne
1043 ; ARM32: dmb 1046 ; ARM32: dmb
1044 1047
1045 ;;;; Cmpxchg 1048 ;;;; Cmpxchg
1046 1049
1047 define i32 @test_atomic_cmpxchg_8(i32 %iptr, i32 %expected, i32 %desired) { 1050 define internal i32 @test_atomic_cmpxchg_8(i32 %iptr, i32 %expected,
1051 i32 %desired) {
1048 entry: 1052 entry:
1049 %trunc_exp = trunc i32 %expected to i8 1053 %trunc_exp = trunc i32 %expected to i8
1050 %trunc_des = trunc i32 %desired to i8 1054 %trunc_des = trunc i32 %desired to i8
1051 %ptr = inttoptr i32 %iptr to i8* 1055 %ptr = inttoptr i32 %iptr to i8*
1052 %old = call i8 @llvm.nacl.atomic.cmpxchg.i8(i8* %ptr, i8 %trunc_exp, 1056 %old = call i8 @llvm.nacl.atomic.cmpxchg.i8(i8* %ptr, i8 %trunc_exp,
1053 i8 %trunc_des, i32 6, i32 6) 1057 i8 %trunc_des, i32 6, i32 6)
1054 %old_ext = zext i8 %old to i32 1058 %old_ext = zext i8 %old to i32
1055 ret i32 %old_ext 1059 ret i32 %old_ext
1056 } 1060 }
1057 ; CHECK-LABEL: test_atomic_cmpxchg_8 1061 ; CHECK-LABEL: test_atomic_cmpxchg_8
1058 ; CHECK: mov eax,{{.*}} 1062 ; CHECK: mov eax,{{.*}}
1059 ; Need to check that eax isn't used as the address register or the desired. 1063 ; Need to check that eax isn't used as the address register or the desired.
1060 ; since it is already used as the *expected* register. 1064 ; since it is already used as the *expected* register.
1061 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],{{[^a]}}l 1065 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],{{[^a]}}l
1062 ; ARM32-LABEL: test_atomic_cmpxchg_8 1066 ; ARM32-LABEL: test_atomic_cmpxchg_8
1063 ; ARM32: dmb 1067 ; ARM32: dmb
1064 ; ARM32: ldrexb 1068 ; ARM32: ldrexb
1065 ; ARM32: cmp 1069 ; ARM32: cmp
1066 ; ARM32: strexbeq 1070 ; ARM32: strexbeq
1067 ; ARM32: {{str|mov}}ne 1071 ; ARM32: {{str|mov}}ne
1068 ; ARM32: cmpeq 1072 ; ARM32: cmpeq
1069 ; ARM32: bne 1073 ; ARM32: bne
1070 ; ARM32: dmb 1074 ; ARM32: dmb
1071 1075
1072 define i32 @test_atomic_cmpxchg_16(i32 %iptr, i32 %expected, i32 %desired) { 1076 define internal i32 @test_atomic_cmpxchg_16(i32 %iptr, i32 %expected,
1077 i32 %desired) {
1073 entry: 1078 entry:
1074 %trunc_exp = trunc i32 %expected to i16 1079 %trunc_exp = trunc i32 %expected to i16
1075 %trunc_des = trunc i32 %desired to i16 1080 %trunc_des = trunc i32 %desired to i16
1076 %ptr = inttoptr i32 %iptr to i16* 1081 %ptr = inttoptr i32 %iptr to i16*
1077 %old = call i16 @llvm.nacl.atomic.cmpxchg.i16(i16* %ptr, i16 %trunc_exp, 1082 %old = call i16 @llvm.nacl.atomic.cmpxchg.i16(i16* %ptr, i16 %trunc_exp,
1078 i16 %trunc_des, i32 6, i32 6) 1083 i16 %trunc_des, i32 6, i32 6)
1079 %old_ext = zext i16 %old to i32 1084 %old_ext = zext i16 %old to i32
1080 ret i32 %old_ext 1085 ret i32 %old_ext
1081 } 1086 }
1082 ; CHECK-LABEL: test_atomic_cmpxchg_16 1087 ; CHECK-LABEL: test_atomic_cmpxchg_16
1083 ; CHECK: mov eax,{{.*}} 1088 ; CHECK: mov eax,{{.*}}
1084 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}],{{[^a]}}x 1089 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}],{{[^a]}}x
1085 ; ARM32-LABEL: test_atomic_cmpxchg_16 1090 ; ARM32-LABEL: test_atomic_cmpxchg_16
1086 ; ARM32: dmb 1091 ; ARM32: dmb
1087 ; ARM32: ldrexh 1092 ; ARM32: ldrexh
1088 ; ARM32: cmp 1093 ; ARM32: cmp
1089 ; ARM32: strexheq 1094 ; ARM32: strexheq
1090 ; ARM32: {{str|mov}}ne 1095 ; ARM32: {{str|mov}}ne
1091 ; ARM32: cmpeq 1096 ; ARM32: cmpeq
1092 ; ARM32: bne 1097 ; ARM32: bne
1093 ; ARM32: dmb 1098 ; ARM32: dmb
1094 1099
1095 define i32 @test_atomic_cmpxchg_32(i32 %iptr, i32 %expected, i32 %desired) { 1100 define internal i32 @test_atomic_cmpxchg_32(i32 %iptr, i32 %expected,
1101 i32 %desired) {
1096 entry: 1102 entry:
1097 %ptr = inttoptr i32 %iptr to i32* 1103 %ptr = inttoptr i32 %iptr to i32*
1098 %old = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected, 1104 %old = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected,
1099 i32 %desired, i32 6, i32 6) 1105 i32 %desired, i32 6, i32 6)
1100 ret i32 %old 1106 ret i32 %old
1101 } 1107 }
1102 ; CHECK-LABEL: test_atomic_cmpxchg_32 1108 ; CHECK-LABEL: test_atomic_cmpxchg_32
1103 ; CHECK: mov eax,{{.*}} 1109 ; CHECK: mov eax,{{.*}}
1104 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],e{{[^a]}} 1110 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],e{{[^a]}}
1105 ; ARM32-LABEL: test_atomic_cmpxchg_32 1111 ; ARM32-LABEL: test_atomic_cmpxchg_32
1106 ; ARM32: dmb 1112 ; ARM32: dmb
1107 ; ARM32: ldrex 1113 ; ARM32: ldrex
1108 ; ARM32: cmp 1114 ; ARM32: cmp
1109 ; ARM32: strexeq 1115 ; ARM32: strexeq
1110 ; ARM32: {{str|mov}}ne 1116 ; ARM32: {{str|mov}}ne
1111 ; ARM32: cmpeq 1117 ; ARM32: cmpeq
1112 ; ARM32: bne 1118 ; ARM32: bne
1113 ; ARM32: dmb 1119 ; ARM32: dmb
1114 1120
1115 define i64 @test_atomic_cmpxchg_64(i32 %iptr, i64 %expected, i64 %desired) { 1121 define internal i64 @test_atomic_cmpxchg_64(i32 %iptr, i64 %expected,
1122 i64 %desired) {
1116 entry: 1123 entry:
1117 %ptr = inttoptr i32 %iptr to i64* 1124 %ptr = inttoptr i32 %iptr to i64*
1118 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected, 1125 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected,
1119 i64 %desired, i32 6, i32 6) 1126 i64 %desired, i32 6, i32 6)
1120 ret i64 %old 1127 ret i64 %old
1121 } 1128 }
1122 ; CHECK-LABEL: test_atomic_cmpxchg_64 1129 ; CHECK-LABEL: test_atomic_cmpxchg_64
1123 ; CHECK: push ebx 1130 ; CHECK: push ebx
1124 ; CHECK-DAG: mov edx 1131 ; CHECK-DAG: mov edx
1125 ; CHECK-DAG: mov eax 1132 ; CHECK-DAG: mov eax
1126 ; CHECK-DAG: mov ecx 1133 ; CHECK-DAG: mov ecx
1127 ; CHECK-DAG: mov ebx 1134 ; CHECK-DAG: mov ebx
1128 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0] 1135 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
1129 ; edx and eax are already the return registers, so they don't actually 1136 ; edx and eax are already the return registers, so they don't actually
1130 ; need to be reshuffled via movs. The next test stores the result 1137 ; need to be reshuffled via movs. The next test stores the result
1131 ; somewhere, so in that case they do need to be mov'ed. 1138 ; somewhere, so in that case they do need to be mov'ed.
1132 ; ARM32-LABEL: test_atomic_cmpxchg_64 1139 ; ARM32-LABEL: test_atomic_cmpxchg_64
1133 ; ARM32: dmb 1140 ; ARM32: dmb
1134 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}} 1141 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
1135 ; ARM32: cmp 1142 ; ARM32: cmp
1136 ; ARM32-NEXT: cmpeq 1143 ; ARM32-NEXT: cmpeq
1137 ; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}} 1144 ; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
1138 ; ARM32: {{str|mov}}ne 1145 ; ARM32: {{str|mov}}ne
1139 ; ARM32: {{str|mov}}ne 1146 ; ARM32: {{str|mov}}ne
1140 ; ARM32: cmpeq 1147 ; ARM32: cmpeq
1141 ; ARM32: bne 1148 ; ARM32: bne
1142 ; ARM32: dmb 1149 ; ARM32: dmb
1143 1150
1144 define i64 @test_atomic_cmpxchg_64_undef(i32 %iptr, i64 %desired) { 1151 define internal i64 @test_atomic_cmpxchg_64_undef(i32 %iptr, i64 %desired) {
1145 entry: 1152 entry:
1146 %ptr = inttoptr i32 %iptr to i64* 1153 %ptr = inttoptr i32 %iptr to i64*
1147 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 undef, 1154 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 undef,
1148 i64 %desired, i32 6, i32 6) 1155 i64 %desired, i32 6, i32 6)
1149 ret i64 %old 1156 ret i64 %old
1150 } 1157 }
1151 ; CHECK-LABEL: test_atomic_cmpxchg_64_undef 1158 ; CHECK-LABEL: test_atomic_cmpxchg_64_undef
1152 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0] 1159 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
1153 ; ARM32-LABEL: test_atomic_cmpxchg_64_undef 1160 ; ARM32-LABEL: test_atomic_cmpxchg_64_undef
1154 ; ARM32: mov r{{[0-9]+}}, #0 1161 ; ARM32: mov r{{[0-9]+}}, #0
1155 ; ARM32: mov r{{[0-9]+}}, #0 1162 ; ARM32: mov r{{[0-9]+}}, #0
1156 ; ARM32: dmb 1163 ; ARM32: dmb
1157 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}} 1164 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
1158 ; ARM32: cmp 1165 ; ARM32: cmp
1159 ; ARM32-NEXT: cmpeq 1166 ; ARM32-NEXT: cmpeq
1160 ; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}} 1167 ; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
1161 ; ARM32: {{str|mov}}ne 1168 ; ARM32: {{str|mov}}ne
1162 ; ARM32: {{str|mov}}ne 1169 ; ARM32: {{str|mov}}ne
1163 ; ARM32: cmpeq 1170 ; ARM32: cmpeq
1164 ; ARM32: bne 1171 ; ARM32: bne
1165 ; ARM32: dmb 1172 ; ARM32: dmb
1166 1173
1167 ; Test a case where %old really does need to be copied out of edx:eax. 1174 ; Test a case where %old really does need to be copied out of edx:eax.
1168 define void @test_atomic_cmpxchg_64_store(i32 %ret_iptr, i32 %iptr, i64 %expecte d, i64 %desired) { 1175 define internal void @test_atomic_cmpxchg_64_store(
1176 i32 %ret_iptr, i32 %iptr, i64 %expected, i64 %desired) {
1169 entry: 1177 entry:
1170 %ptr = inttoptr i32 %iptr to i64* 1178 %ptr = inttoptr i32 %iptr to i64*
1171 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected, 1179 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected,
1172 i64 %desired, i32 6, i32 6) 1180 i64 %desired, i32 6, i32 6)
1173 %__6 = inttoptr i32 %ret_iptr to i64* 1181 %__6 = inttoptr i32 %ret_iptr to i64*
1174 store i64 %old, i64* %__6, align 1 1182 store i64 %old, i64* %__6, align 1
1175 ret void 1183 ret void
1176 } 1184 }
1177 ; CHECK-LABEL: test_atomic_cmpxchg_64_store 1185 ; CHECK-LABEL: test_atomic_cmpxchg_64_store
1178 ; CHECK: push ebx 1186 ; CHECK: push ebx
(...skipping 13 matching lines...) Expand all
1192 ; ARM32: {{str|mov}}ne 1200 ; ARM32: {{str|mov}}ne
1193 ; ARM32: {{str|mov}}ne 1201 ; ARM32: {{str|mov}}ne
1194 ; ARM32: cmpeq 1202 ; ARM32: cmpeq
1195 ; ARM32: bne 1203 ; ARM32: bne
1196 ; ARM32: dmb 1204 ; ARM32: dmb
1197 ; ARM32: str 1205 ; ARM32: str
1198 ; ARM32: str 1206 ; ARM32: str
1199 1207
1200 ; Test with some more register pressure. When we have an alloca, ebp is 1208 ; Test with some more register pressure. When we have an alloca, ebp is
1201 ; used to manage the stack frame, so it cannot be used as a register either. 1209 ; used to manage the stack frame, so it cannot be used as a register either.
1202 define i64 @test_atomic_cmpxchg_64_alloca(i32 %iptr, i64 %expected, i64 %desired ) { 1210 define internal i64 @test_atomic_cmpxchg_64_alloca(i32 %iptr, i64 %expected,
1211 i64 %desired) {
1203 entry: 1212 entry:
1204 br label %eblock ; Disable alloca optimization 1213 br label %eblock ; Disable alloca optimization
1205 eblock: 1214 eblock:
1206 %alloca_ptr = alloca i8, i32 16, align 16 1215 %alloca_ptr = alloca i8, i32 16, align 16
1207 %ptr = inttoptr i32 %iptr to i64* 1216 %ptr = inttoptr i32 %iptr to i64*
1208 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected, 1217 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected,
1209 i64 %desired, i32 6, i32 6) 1218 i64 %desired, i32 6, i32 6)
1210 store i8 0, i8* %alloca_ptr, align 1 1219 store i8 0, i8* %alloca_ptr, align 1
1211 store i8 1, i8* %alloca_ptr, align 1 1220 store i8 1, i8* %alloca_ptr, align 1
1212 store i8 2, i8* %alloca_ptr, align 1 1221 store i8 2, i8* %alloca_ptr, align 1
(...skipping 20 matching lines...) Expand all
1233 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}} 1242 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
1234 ; ARM32: cmp 1243 ; ARM32: cmp
1235 ; ARM32-NEXT: cmpeq 1244 ; ARM32-NEXT: cmpeq
1236 ; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}} 1245 ; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
1237 ; ARM32: {{str|mov}}ne 1246 ; ARM32: {{str|mov}}ne
1238 ; ARM32: {{str|mov}}ne 1247 ; ARM32: {{str|mov}}ne
1239 ; ARM32: cmpeq 1248 ; ARM32: cmpeq
1240 ; ARM32: bne 1249 ; ARM32: bne
1241 ; ARM32: dmb 1250 ; ARM32: dmb
1242 1251
1243 define i32 @test_atomic_cmpxchg_32_ignored(i32 %iptr, i32 %expected, i32 %desire d) { 1252 define internal i32 @test_atomic_cmpxchg_32_ignored(i32 %iptr, i32 %expected,
1253 i32 %desired) {
1244 entry: 1254 entry:
1245 %ptr = inttoptr i32 %iptr to i32* 1255 %ptr = inttoptr i32 %iptr to i32*
1246 %ignored = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected, 1256 %ignored = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected,
1247 i32 %desired, i32 6, i32 6) 1257 i32 %desired, i32 6, i32 6)
1248 ret i32 0 1258 ret i32 0
1249 } 1259 }
1250 ; CHECK-LABEL: test_atomic_cmpxchg_32_ignored 1260 ; CHECK-LABEL: test_atomic_cmpxchg_32_ignored
1251 ; CHECK: mov eax,{{.*}} 1261 ; CHECK: mov eax,{{.*}}
1252 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}] 1262 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
1253 ; ARM32-LABEL: test_atomic_cmpxchg_32_ignored 1263 ; ARM32-LABEL: test_atomic_cmpxchg_32_ignored
1254 ; ARM32: dmb 1264 ; ARM32: dmb
1255 ; ARM32: ldrex 1265 ; ARM32: ldrex
1256 ; ARM32: cmp 1266 ; ARM32: cmp
1257 ; ARM32: strexeq 1267 ; ARM32: strexeq
1258 ; ARM32: {{str|mov}}ne 1268 ; ARM32: {{str|mov}}ne
1259 ; ARM32: cmpeq 1269 ; ARM32: cmpeq
1260 ; ARM32: bne 1270 ; ARM32: bne
1261 ; ARM32: dmb 1271 ; ARM32: dmb
1262 1272
1263 define i64 @test_atomic_cmpxchg_64_ignored(i32 %iptr, i64 %expected, i64 %desire d) { 1273 define internal i64 @test_atomic_cmpxchg_64_ignored(i32 %iptr, i64 %expected,
1274 i64 %desired) {
1264 entry: 1275 entry:
1265 %ptr = inttoptr i32 %iptr to i64* 1276 %ptr = inttoptr i32 %iptr to i64*
1266 %ignored = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected, 1277 %ignored = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected,
1267 i64 %desired, i32 6, i32 6) 1278 i64 %desired, i32 6, i32 6)
1268 ret i64 0 1279 ret i64 0
1269 } 1280 }
1270 ; CHECK-LABEL: test_atomic_cmpxchg_64_ignored 1281 ; CHECK-LABEL: test_atomic_cmpxchg_64_ignored
1271 ; CHECK: push ebx 1282 ; CHECK: push ebx
1272 ; CHECK-DAG: mov edx 1283 ; CHECK-DAG: mov edx
1273 ; CHECK-DAG: mov eax 1284 ; CHECK-DAG: mov eax
1274 ; CHECK-DAG: mov ecx 1285 ; CHECK-DAG: mov ecx
1275 ; CHECK-DAG: mov ebx 1286 ; CHECK-DAG: mov ebx
1276 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0] 1287 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
1277 ; ARM32-LABEL: test_atomic_cmpxchg_64_ignored 1288 ; ARM32-LABEL: test_atomic_cmpxchg_64_ignored
1278 ; ARM32: dmb 1289 ; ARM32: dmb
1279 ; ARM32: ldrexd [[R0:r[0-9]+]], [[R1:r[0-9]+]], {{[[]}}[[PTR:r[0-9]+]]{{[]]}} 1290 ; ARM32: ldrexd [[R0:r[0-9]+]], [[R1:r[0-9]+]], {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
1280 ; ARM32: cmp 1291 ; ARM32: cmp
1281 ; ARM32-NEXT: cmpeq 1292 ; ARM32-NEXT: cmpeq
1282 ; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}} 1293 ; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
1283 ; ARM32O2-NOT: {{str|mov}}ne [[R0]] 1294 ; ARM32O2-NOT: {{str|mov}}ne [[R0]]
1284 ; ARM32O2-NOT: {{str|mov}}ne [[R1]] 1295 ; ARM32O2-NOT: {{str|mov}}ne [[R1]]
1285 ; ARM32: cmpeq 1296 ; ARM32: cmpeq
1286 ; ARM32: bne 1297 ; ARM32: bne
1287 ; ARM32: dmb 1298 ; ARM32: dmb
1288 1299
1289 ;;;; Fence and is-lock-free. 1300 ;;;; Fence and is-lock-free.
1290 1301
1291 define void @test_atomic_fence() { 1302 define internal void @test_atomic_fence() {
1292 entry: 1303 entry:
1293 call void @llvm.nacl.atomic.fence(i32 6) 1304 call void @llvm.nacl.atomic.fence(i32 6)
1294 ret void 1305 ret void
1295 } 1306 }
1296 ; CHECK-LABEL: test_atomic_fence 1307 ; CHECK-LABEL: test_atomic_fence
1297 ; CHECK: mfence 1308 ; CHECK: mfence
1298 ; ARM32-LABEL: test_atomic_fence 1309 ; ARM32-LABEL: test_atomic_fence
1299 ; ARM32: dmb sy 1310 ; ARM32: dmb sy
1300 1311
1301 define void @test_atomic_fence_all() { 1312 define internal void @test_atomic_fence_all() {
1302 entry: 1313 entry:
1303 call void @llvm.nacl.atomic.fence.all() 1314 call void @llvm.nacl.atomic.fence.all()
1304 ret void 1315 ret void
1305 } 1316 }
1306 ; CHECK-LABEL: test_atomic_fence_all 1317 ; CHECK-LABEL: test_atomic_fence_all
1307 ; CHECK: mfence 1318 ; CHECK: mfence
1308 ; ARM32-LABEL: test_atomic_fence_all 1319 ; ARM32-LABEL: test_atomic_fence_all
1309 ; ARM32: dmb sy 1320 ; ARM32: dmb sy
1310 1321
1311 define i32 @test_atomic_is_lock_free(i32 %iptr) { 1322 define internal i32 @test_atomic_is_lock_free(i32 %iptr) {
1312 entry: 1323 entry:
1313 %ptr = inttoptr i32 %iptr to i8* 1324 %ptr = inttoptr i32 %iptr to i8*
1314 %i = call i1 @llvm.nacl.atomic.is.lock.free(i32 4, i8* %ptr) 1325 %i = call i1 @llvm.nacl.atomic.is.lock.free(i32 4, i8* %ptr)
1315 %r = zext i1 %i to i32 1326 %r = zext i1 %i to i32
1316 ret i32 %r 1327 ret i32 %r
1317 } 1328 }
1318 ; CHECK-LABEL: test_atomic_is_lock_free 1329 ; CHECK-LABEL: test_atomic_is_lock_free
1319 ; CHECK: mov {{.*}},0x1 1330 ; CHECK: mov {{.*}},0x1
1320 ; ARM32-LABEL: test_atomic_is_lock_free 1331 ; ARM32-LABEL: test_atomic_is_lock_free
1321 ; ARM32: movw {{.*}}, #1 1332 ; ARM32: movw {{.*}}, #1
1322 1333
1323 define i32 @test_not_lock_free(i32 %iptr) { 1334 define internal i32 @test_not_lock_free(i32 %iptr) {
1324 entry: 1335 entry:
1325 %ptr = inttoptr i32 %iptr to i8* 1336 %ptr = inttoptr i32 %iptr to i8*
1326 %i = call i1 @llvm.nacl.atomic.is.lock.free(i32 7, i8* %ptr) 1337 %i = call i1 @llvm.nacl.atomic.is.lock.free(i32 7, i8* %ptr)
1327 %r = zext i1 %i to i32 1338 %r = zext i1 %i to i32
1328 ret i32 %r 1339 ret i32 %r
1329 } 1340 }
1330 ; CHECK-LABEL: test_not_lock_free 1341 ; CHECK-LABEL: test_not_lock_free
1331 ; CHECK: mov {{.*}},0x0 1342 ; CHECK: mov {{.*}},0x0
1332 ; ARM32-LABEL: test_not_lock_free 1343 ; ARM32-LABEL: test_not_lock_free
1333 ; ARM32: mov {{.*}}, #0 1344 ; ARM32: mov {{.*}}, #0
1334 1345
1335 define i32 @test_atomic_is_lock_free_ignored(i32 %iptr) { 1346 define internal i32 @test_atomic_is_lock_free_ignored(i32 %iptr) {
1336 entry: 1347 entry:
1337 %ptr = inttoptr i32 %iptr to i8* 1348 %ptr = inttoptr i32 %iptr to i8*
1338 %ignored = call i1 @llvm.nacl.atomic.is.lock.free(i32 4, i8* %ptr) 1349 %ignored = call i1 @llvm.nacl.atomic.is.lock.free(i32 4, i8* %ptr)
1339 ret i32 0 1350 ret i32 0
1340 } 1351 }
1341 ; CHECK-LABEL: test_atomic_is_lock_free_ignored 1352 ; CHECK-LABEL: test_atomic_is_lock_free_ignored
1342 ; CHECK: mov {{.*}},0x0 1353 ; CHECK: mov {{.*}},0x0
1343 ; This can get optimized out, because it's side-effect-free. 1354 ; This can get optimized out, because it's side-effect-free.
1344 ; O2-LABEL: test_atomic_is_lock_free_ignored 1355 ; O2-LABEL: test_atomic_is_lock_free_ignored
1345 ; O2-NOT: mov {{.*}}, 1 1356 ; O2-NOT: mov {{.*}}, 1
1346 ; O2: mov {{.*}},0x0 1357 ; O2: mov {{.*}},0x0
1347 ; ARM32O2-LABEL: test_atomic_is_lock_free_ignored 1358 ; ARM32O2-LABEL: test_atomic_is_lock_free_ignored
1348 ; ARM32O2-NOT: mov {{.*}}, #1 1359 ; ARM32O2-NOT: mov {{.*}}, #1
1349 ; ARM32O2: mov {{.*}}, #0 1360 ; ARM32O2: mov {{.*}}, #0
1350 1361
1351 ; TODO(jvoung): at some point we can take advantage of the 1362 ; TODO(jvoung): at some point we can take advantage of the
1352 ; fact that nacl.atomic.is.lock.free will resolve to a constant 1363 ; fact that nacl.atomic.is.lock.free will resolve to a constant
1353 ; (which adds DCE opportunities). Once we optimize, the test expectations 1364 ; (which adds DCE opportunities). Once we optimize, the test expectations
1354 ; for this case should change. 1365 ; for this case should change.
1355 define i32 @test_atomic_is_lock_free_can_dce(i32 %iptr, i32 %x, i32 %y) { 1366 define internal i32 @test_atomic_is_lock_free_can_dce(i32 %iptr, i32 %x,
1367 i32 %y) {
1356 entry: 1368 entry:
1357 %ptr = inttoptr i32 %iptr to i8* 1369 %ptr = inttoptr i32 %iptr to i8*
1358 %i = call i1 @llvm.nacl.atomic.is.lock.free(i32 4, i8* %ptr) 1370 %i = call i1 @llvm.nacl.atomic.is.lock.free(i32 4, i8* %ptr)
1359 %i_ext = zext i1 %i to i32 1371 %i_ext = zext i1 %i to i32
1360 %cmp = icmp eq i32 %i_ext, 1 1372 %cmp = icmp eq i32 %i_ext, 1
1361 br i1 %cmp, label %lock_free, label %not_lock_free 1373 br i1 %cmp, label %lock_free, label %not_lock_free
1362 lock_free: 1374 lock_free:
1363 ret i32 %i_ext 1375 ret i32 %i_ext
1364 1376
1365 not_lock_free: 1377 not_lock_free:
1366 %z = add i32 %x, %y 1378 %z = add i32 %x, %y
1367 ret i32 %z 1379 ret i32 %z
1368 } 1380 }
1369 ; CHECK-LABEL: test_atomic_is_lock_free_can_dce 1381 ; CHECK-LABEL: test_atomic_is_lock_free_can_dce
1370 ; CHECK: mov {{.*}},0x1 1382 ; CHECK: mov {{.*}},0x1
1371 ; CHECK: ret 1383 ; CHECK: ret
1372 ; CHECK: add 1384 ; CHECK: add
1373 ; CHECK: ret 1385 ; CHECK: ret
1374 1386
1375 ; Test the liveness / register allocation properties of the xadd instruction. 1387 ; Test the liveness / register allocation properties of the xadd instruction.
1376 ; Make sure we model that the Src register is modified and therefore it can't 1388 ; Make sure we model that the Src register is modified and therefore it can't
1377 ; share a register with an overlapping live range, even if the result of the 1389 ; share a register with an overlapping live range, even if the result of the
1378 ; xadd instruction is unused. 1390 ; xadd instruction is unused.
1379 define void @test_xadd_regalloc() { 1391 define internal void @test_xadd_regalloc() {
1380 entry: 1392 entry:
1381 br label %body 1393 br label %body
1382 body: 1394 body:
1383 %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ] 1395 %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ]
1384 %g = bitcast [4 x i8]* @Global32 to i32* 1396 %g = bitcast [4 x i8]* @Global32 to i32*
1385 %unused = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %g, i32 %i, i32 6) 1397 %unused = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %g, i32 %i, i32 6)
1386 %i_plus_1 = add i32 %i, 1 1398 %i_plus_1 = add i32 %i, 1
1387 %cmp = icmp eq i32 %i_plus_1, 1001 1399 %cmp = icmp eq i32 %i_plus_1, 1001
1388 br i1 %cmp, label %done, label %body 1400 br i1 %cmp, label %done, label %body
1389 done: 1401 done:
1390 ret void 1402 ret void
1391 } 1403 }
1392 ; O2-LABEL: test_xadd_regalloc 1404 ; O2-LABEL: test_xadd_regalloc
1393 ;;; Some register will be used in the xadd instruction. 1405 ;;; Some register will be used in the xadd instruction.
1394 ; O2: lock xadd DWORD PTR {{.*}},[[REG:e..]] 1406 ; O2: lock xadd DWORD PTR {{.*}},[[REG:e..]]
1395 ;;; Make sure that register isn't used again, e.g. as the induction variable. 1407 ;;; Make sure that register isn't used again, e.g. as the induction variable.
1396 ; O2-NOT: [[REG]] 1408 ; O2-NOT: [[REG]]
1397 ; O2: ret 1409 ; O2: ret
1398 1410
1399 ; Do the same test for the xchg instruction instead of xadd. 1411 ; Do the same test for the xchg instruction instead of xadd.
1400 define void @test_xchg_regalloc() { 1412 define internal void @test_xchg_regalloc() {
1401 entry: 1413 entry:
1402 br label %body 1414 br label %body
1403 body: 1415 body:
1404 %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ] 1416 %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ]
1405 %g = bitcast [4 x i8]* @Global32 to i32* 1417 %g = bitcast [4 x i8]* @Global32 to i32*
1406 %unused = call i32 @llvm.nacl.atomic.rmw.i32(i32 6, i32* %g, i32 %i, i32 6) 1418 %unused = call i32 @llvm.nacl.atomic.rmw.i32(i32 6, i32* %g, i32 %i, i32 6)
1407 %i_plus_1 = add i32 %i, 1 1419 %i_plus_1 = add i32 %i, 1
1408 %cmp = icmp eq i32 %i_plus_1, 1001 1420 %cmp = icmp eq i32 %i_plus_1, 1001
1409 br i1 %cmp, label %done, label %body 1421 br i1 %cmp, label %done, label %body
1410 done: 1422 done:
1411 ret void 1423 ret void
1412 } 1424 }
1413 ; O2-LABEL: test_xchg_regalloc 1425 ; O2-LABEL: test_xchg_regalloc
1414 ;;; Some register will be used in the xchg instruction. 1426 ;;; Some register will be used in the xchg instruction.
1415 ; O2: xchg DWORD PTR {{.*}},[[REG:e..]] 1427 ; O2: xchg DWORD PTR {{.*}},[[REG:e..]]
1416 ;;; Make sure that register isn't used again, e.g. as the induction variable. 1428 ;;; Make sure that register isn't used again, e.g. as the induction variable.
1417 ; O2-NOT: [[REG]] 1429 ; O2-NOT: [[REG]]
1418 ; O2: ret 1430 ; O2: ret
1419 1431
1420 ; Same test for cmpxchg. 1432 ; Same test for cmpxchg.
1421 define void @test_cmpxchg_regalloc() { 1433 define internal void @test_cmpxchg_regalloc() {
1422 entry: 1434 entry:
1423 br label %body 1435 br label %body
1424 body: 1436 body:
1425 %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ] 1437 %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ]
1426 %g = bitcast [4 x i8]* @Global32 to i32* 1438 %g = bitcast [4 x i8]* @Global32 to i32*
1427 %unused = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %g, i32 %i, i32 %i, i32 6, i32 6) 1439 %unused = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %g, i32 %i, i32 %i, i32 6, i32 6)
1428 %i_plus_1 = add i32 %i, 1 1440 %i_plus_1 = add i32 %i, 1
1429 %cmp = icmp eq i32 %i_plus_1, 1001 1441 %cmp = icmp eq i32 %i_plus_1, 1001
1430 br i1 %cmp, label %done, label %body 1442 br i1 %cmp, label %done, label %body
1431 done: 1443 done:
1432 ret void 1444 ret void
1433 } 1445 }
1434 ; O2-LABEL: test_cmpxchg_regalloc 1446 ; O2-LABEL: test_cmpxchg_regalloc
1435 ;;; eax and some other register will be used in the cmpxchg instruction. 1447 ;;; eax and some other register will be used in the cmpxchg instruction.
1436 ; O2: lock cmpxchg DWORD PTR {{.*}},[[REG:e..]] 1448 ; O2: lock cmpxchg DWORD PTR {{.*}},[[REG:e..]]
1437 ;;; Make sure eax isn't used again, e.g. as the induction variable. 1449 ;;; Make sure eax isn't used again, e.g. as the induction variable.
1438 ; O2-NOT: eax 1450 ; O2-NOT: eax
1439 ; O2: ret 1451 ; O2: ret
1440 1452
1441 ; Same test for cmpxchg8b. 1453 ; Same test for cmpxchg8b.
1442 define void @test_cmpxchg8b_regalloc() { 1454 define internal void @test_cmpxchg8b_regalloc() {
1443 entry: 1455 entry:
1444 br label %body 1456 br label %body
1445 body: 1457 body:
1446 %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ] 1458 %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ]
1447 %g = bitcast [8 x i8]* @Global64 to i64* 1459 %g = bitcast [8 x i8]* @Global64 to i64*
1448 %i_64 = zext i32 %i to i64 1460 %i_64 = zext i32 %i to i64
1449 %unused = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %g, i64 %i_64, i64 %i_64 , i32 6, i32 6) 1461 %unused = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %g, i64 %i_64, i64 %i_64 , i32 6, i32 6)
1450 %i_plus_1 = add i32 %i, 1 1462 %i_plus_1 = add i32 %i, 1
1451 %cmp = icmp eq i32 %i_plus_1, 1001 1463 %cmp = icmp eq i32 %i_plus_1, 1001
1452 br i1 %cmp, label %done, label %body 1464 br i1 %cmp, label %done, label %body
1453 done: 1465 done:
1454 ret void 1466 ret void
1455 } 1467 }
1456 ; O2-LABEL: test_cmpxchg8b_regalloc 1468 ; O2-LABEL: test_cmpxchg8b_regalloc
1457 ;;; eax and some other register will be used in the cmpxchg instruction. 1469 ;;; eax and some other register will be used in the cmpxchg instruction.
1458 ; O2: lock cmpxchg8b QWORD PTR 1470 ; O2: lock cmpxchg8b QWORD PTR
1459 ;;; Make sure eax/ecx/edx/ebx aren't used again, e.g. as the induction variable. 1471 ;;; Make sure eax/ecx/edx/ebx aren't used again, e.g. as the induction variable.
1460 ; O2-NOT: {{eax|ecx|edx|ebx}} 1472 ; O2-NOT: {{eax|ecx|edx|ebx}}
1461 ; O2: pop ebx 1473 ; O2: pop ebx
OLDNEW
« no previous file with comments | « tests_lit/llvm2ice_tests/nacl-atomic-fence-all.ll ('k') | tests_lit/llvm2ice_tests/nacl-mem-intrinsics.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698