| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |