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

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

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

Powered by Google App Engine
This is Rietveld 408576698