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