| OLD | NEW |
| 1 ; Tests various aspects of x86 branch encodings (near vs far, | 1 ; Tests various aspects of x86 branch encodings (near vs far, |
| 2 ; forward vs backward, using CFG labels, or local labels). | 2 ; forward vs backward, using CFG labels, or local labels). |
| 3 | 3 |
| 4 ; Use -ffunction-sections so that the offsets reset for each function. | 4 ; Use -ffunction-sections so that the offsets reset for each function. |
| 5 ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 \ | 5 ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 \ |
| 6 ; RUN: -ffunction-sections | FileCheck %s | 6 ; RUN: -ffunction-sections | FileCheck %s |
| 7 | 7 |
| 8 ; Use atomic ops as filler, which shouldn't get optimized out. | 8 ; Use atomic ops as filler, which shouldn't get optimized out. |
| 9 declare void @llvm.nacl.atomic.store.i32(i32, i32*, i32) | 9 declare void @llvm.nacl.atomic.store.i32(i32, i32*, i32) |
| 10 declare i32 @llvm.nacl.atomic.load.i32(i32*, i32) | 10 declare i32 @llvm.nacl.atomic.load.i32(i32*, i32) |
| 11 declare i32 @llvm.nacl.atomic.rmw.i32(i32, i32*, i32, i32) | 11 declare i32 @llvm.nacl.atomic.rmw.i32(i32, i32*, i32, i32) |
| 12 | 12 |
| 13 define void @test_near_backward(i32 %iptr, i32 %val) { | 13 define internal void @test_near_backward(i32 %iptr, i32 %val) { |
| 14 entry: | 14 entry: |
| 15 br label %next | 15 br label %next |
| 16 next: | 16 next: |
| 17 %ptr = inttoptr i32 %iptr to i32* | 17 %ptr = inttoptr i32 %iptr to i32* |
| 18 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | 18 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) |
| 19 br label %next2 | 19 br label %next2 |
| 20 next2: | 20 next2: |
| 21 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | 21 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) |
| 22 %cmp = icmp ult i32 %val, 0 | 22 %cmp = icmp ult i32 %val, 0 |
| 23 br i1 %cmp, label %next2, label %next | 23 br i1 %cmp, label %next2, label %next |
| 24 } | 24 } |
| 25 | 25 |
| 26 ; CHECK-LABEL: test_near_backward | 26 ; CHECK-LABEL: test_near_backward |
| 27 ; CHECK: 8: {{.*}} mov DWORD PTR | 27 ; CHECK: 8: {{.*}} mov DWORD PTR |
| 28 ; CHECK-NEXT: a: {{.*}} mfence | 28 ; CHECK-NEXT: a: {{.*}} mfence |
| 29 ; CHECK-NEXT: d: {{.*}} mov DWORD PTR | 29 ; CHECK-NEXT: d: {{.*}} mov DWORD PTR |
| 30 ; CHECK-NEXT: f: {{.*}} mfence | 30 ; CHECK-NEXT: f: {{.*}} mfence |
| 31 ; CHECK-NEXT: 12: {{.*}} cmp | 31 ; CHECK-NEXT: 12: {{.*}} cmp |
| 32 ; CHECK-NEXT: 15: 72 f6 jb d | 32 ; CHECK-NEXT: 15: 72 f6 jb d |
| 33 ; CHECK-NEXT: 17: eb ef jmp 8 | 33 ; CHECK-NEXT: 17: eb ef jmp 8 |
| 34 | 34 |
| 35 ; Test one of the backward branches being too large for 8 bits | 35 ; Test one of the backward branches being too large for 8 bits |
| 36 ; and one being just okay. | 36 ; and one being just okay. |
| 37 define void @test_far_backward1(i32 %iptr, i32 %val) { | 37 define internal void @test_far_backward1(i32 %iptr, i32 %val) { |
| 38 entry: | 38 entry: |
| 39 br label %next | 39 br label %next |
| 40 next: | 40 next: |
| 41 %ptr = inttoptr i32 %iptr to i32* | 41 %ptr = inttoptr i32 %iptr to i32* |
| 42 %tmp = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | 42 %tmp = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) |
| 43 br label %next2 | 43 br label %next2 |
| 44 next2: | 44 next2: |
| 45 call void @llvm.nacl.atomic.store.i32(i32 %tmp, i32* %ptr, i32 6) | 45 call void @llvm.nacl.atomic.store.i32(i32 %tmp, i32* %ptr, i32 6) |
| 46 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | 46 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) |
| 47 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | 47 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 72 | 72 |
| 73 ; CHECK-LABEL: test_far_backward1 | 73 ; CHECK-LABEL: test_far_backward1 |
| 74 ; CHECK: 8: {{.*}} mov {{.*}},DWORD PTR [e{{[^s]}} | 74 ; CHECK: 8: {{.*}} mov {{.*}},DWORD PTR [e{{[^s]}} |
| 75 ; CHECK-NEXT: a: {{.*}} mov DWORD PTR | 75 ; CHECK-NEXT: a: {{.*}} mov DWORD PTR |
| 76 ; CHECK-NEXT: c: {{.*}} mfence | 76 ; CHECK-NEXT: c: {{.*}} mfence |
| 77 ; CHECK: 85: 77 83 ja a | 77 ; CHECK: 85: 77 83 ja a |
| 78 ; CHECK-NEXT: 87: e9 7c ff ff ff jmp 8 | 78 ; CHECK-NEXT: 87: e9 7c ff ff ff jmp 8 |
| 79 | 79 |
| 80 ; Same as test_far_backward1, but with the conditional branch being | 80 ; Same as test_far_backward1, but with the conditional branch being |
| 81 ; the one that is too far. | 81 ; the one that is too far. |
| 82 define void @test_far_backward2(i32 %iptr, i32 %val) { | 82 define internal void @test_far_backward2(i32 %iptr, i32 %val) { |
| 83 entry: | 83 entry: |
| 84 br label %next | 84 br label %next |
| 85 next: | 85 next: |
| 86 %ptr = inttoptr i32 %iptr to i32* | 86 %ptr = inttoptr i32 %iptr to i32* |
| 87 %tmp = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | 87 %tmp = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) |
| 88 %tmp2 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | 88 %tmp2 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) |
| 89 %tmp3 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | 89 %tmp3 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) |
| 90 %tmp4 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | 90 %tmp4 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) |
| 91 %tmp5 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | 91 %tmp5 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) |
| 92 br label %next2 | 92 br label %next2 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 119 } | 119 } |
| 120 | 120 |
| 121 ; CHECK-LABEL: test_far_backward2 | 121 ; CHECK-LABEL: test_far_backward2 |
| 122 ; CHECK: c: {{.*}} mov {{.*}},DWORD PTR [e{{[^s]}} | 122 ; CHECK: c: {{.*}} mov {{.*}},DWORD PTR [e{{[^s]}} |
| 123 ; CHECK: 14: {{.*}} mov {{.*}},DWORD PTR | 123 ; CHECK: 14: {{.*}} mov {{.*}},DWORD PTR |
| 124 ; CHECK-NEXT: 16: {{.*}} mov DWORD PTR | 124 ; CHECK-NEXT: 16: {{.*}} mov DWORD PTR |
| 125 ; CHECK-NEXT: 18: {{.*}} mfence | 125 ; CHECK-NEXT: 18: {{.*}} mfence |
| 126 ; CHECK: 8c: 0f 8e 7a ff ff ff jle c | 126 ; CHECK: 8c: 0f 8e 7a ff ff ff jle c |
| 127 ; CHECK-NEXT: 92: eb 82 jmp 16 | 127 ; CHECK-NEXT: 92: eb 82 jmp 16 |
| 128 | 128 |
| 129 define void @test_near_forward(i32 %iptr, i32 %val) { | 129 define internal void @test_near_forward(i32 %iptr, i32 %val) { |
| 130 entry: | 130 entry: |
| 131 br label %next1 | 131 br label %next1 |
| 132 next1: | 132 next1: |
| 133 %ptr = inttoptr i32 %iptr to i32* | 133 %ptr = inttoptr i32 %iptr to i32* |
| 134 %cmp = icmp ult i32 %val, 0 | 134 %cmp = icmp ult i32 %val, 0 |
| 135 br i1 %cmp, label %next3, label %next2 | 135 br i1 %cmp, label %next3, label %next2 |
| 136 next2: | 136 next2: |
| 137 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | 137 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) |
| 138 br label %next3 | 138 br label %next3 |
| 139 next3: | 139 next3: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 150 ; CHECK-NEXT: 16: {{.*}} mov DWORD PTR | 150 ; CHECK-NEXT: 16: {{.*}} mov DWORD PTR |
| 151 ; CHECK: 1b: eb eb jmp 8 | 151 ; CHECK: 1b: eb eb jmp 8 |
| 152 | 152 |
| 153 | 153 |
| 154 ; Unlike forward branches to cfg nodes, "local" forward branches | 154 ; Unlike forward branches to cfg nodes, "local" forward branches |
| 155 ; always use a 1 byte displacement. | 155 ; always use a 1 byte displacement. |
| 156 ; Check local forward branches, followed by a near backward branch | 156 ; Check local forward branches, followed by a near backward branch |
| 157 ; to make sure that the instruction size accounting for the forward | 157 ; to make sure that the instruction size accounting for the forward |
| 158 ; branches are correct, by the time the backward branch is hit. | 158 ; branches are correct, by the time the backward branch is hit. |
| 159 ; A 64-bit compare happens to use local forward branches. | 159 ; A 64-bit compare happens to use local forward branches. |
| 160 define void @test_local_forward_then_back(i64 %val64, i32 %iptr, i32 %val) { | 160 define internal void @test_local_forward_then_back(i64 %val64, i32 %iptr, |
| 161 i32 %val) { |
| 161 entry: | 162 entry: |
| 162 br label %next | 163 br label %next |
| 163 next: | 164 next: |
| 164 %ptr = inttoptr i32 %iptr to i32* | 165 %ptr = inttoptr i32 %iptr to i32* |
| 165 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | 166 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) |
| 166 br label %next2 | 167 br label %next2 |
| 167 next2: | 168 next2: |
| 168 %cmp = icmp ult i64 %val64, 0 | 169 %cmp = icmp ult i64 %val64, 0 |
| 169 br i1 %cmp, label %next, label %next2 | 170 br i1 %cmp, label %next, label %next2 |
| 170 } | 171 } |
| 171 ; CHECK-LABEL: test_local_forward_then_back | 172 ; CHECK-LABEL: test_local_forward_then_back |
| 172 ; CHECK: {{.*}} mov DWORD PTR | 173 ; CHECK: {{.*}} mov DWORD PTR |
| 173 ; CHECK-NEXT: {{.*}} mfence | 174 ; CHECK-NEXT: {{.*}} mfence |
| 174 ; CHECK-NEXT: 16: {{.*}} mov {{.*}},0x1 | 175 ; CHECK-NEXT: 16: {{.*}} mov {{.*}},0x1 |
| 175 ; CHECK-NEXT: {{.*}} cmp | 176 ; CHECK-NEXT: {{.*}} cmp |
| 176 ; CHECK-NEXT: {{.*}} jb | 177 ; CHECK-NEXT: {{.*}} jb |
| 177 ; CHECK: {{.*}} jne | 178 ; CHECK: {{.*}} jne |
| 178 ; CHECK: {{.*}} jmp 16 | 179 ; CHECK: {{.*}} jmp 16 |
| 179 | 180 |
| 180 | 181 |
| 181 ; Test that backward local branches also work and are small. | 182 ; Test that backward local branches also work and are small. |
| 182 ; Some of the atomic instructions use a cmpxchg loop. | 183 ; Some of the atomic instructions use a cmpxchg loop. |
| 183 define void @test_local_backward(i64 %val64, i32 %iptr, i32 %val) { | 184 define internal void @test_local_backward(i64 %val64, i32 %iptr, i32 %val) { |
| 184 entry: | 185 entry: |
| 185 br label %next | 186 br label %next |
| 186 next: | 187 next: |
| 187 %ptr = inttoptr i32 %iptr to i32* | 188 %ptr = inttoptr i32 %iptr to i32* |
| 188 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 5, i32* %ptr, i32 %val, i32 6) | 189 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 5, i32* %ptr, i32 %val, i32 6) |
| 189 br label %next2 | 190 br label %next2 |
| 190 next2: | 191 next2: |
| 191 %success = icmp eq i32 1, %a | 192 %success = icmp eq i32 1, %a |
| 192 br i1 %success, label %next, label %next2 | 193 br i1 %success, label %next, label %next2 |
| 193 } | 194 } |
| 194 ; CHECK-LABEL: test_local_backward | 195 ; CHECK-LABEL: test_local_backward |
| 195 ; CHECK: 9: {{.*}} mov {{.*}},DWORD | 196 ; CHECK: 9: {{.*}} mov {{.*}},DWORD |
| 196 ; CHECK: b: {{.*}} mov | 197 ; CHECK: b: {{.*}} mov |
| 197 ; CHECK-NEXT: d: {{.*}} xor | 198 ; CHECK-NEXT: d: {{.*}} xor |
| 198 ; CHECK-NEXT: f: {{.*}} lock cmpxchg | 199 ; CHECK-NEXT: f: {{.*}} lock cmpxchg |
| 199 ; CHECK-NEXT: 13: 75 f6 jne b | 200 ; CHECK-NEXT: 13: 75 f6 jne b |
| 200 ; CHECK: 1c: 74 eb je 9 | 201 ; CHECK: 1c: 74 eb je 9 |
| OLD | NEW |