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 |