OLD | NEW |
---|---|
(Empty) | |
1 ; Tests various aspects of x86 branch encodings (near vs far, | |
2 ; forward vs backward, using CFG labels, or local labels). | |
3 | |
4 ; Use -ffunction-sections so that the offsets reset for each function. | |
5 ; RUN: %p2i -i %s --args -O2 --verbose none -ffunction-sections \ | |
6 ; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \ | |
7 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s | |
8 ; RUN: %p2i -i %s --args --verbose none | FileCheck --check-prefix=ERRORS %s | |
9 | |
10 ; Use atomic ops as filler, which shouldn't get optimized out. | |
11 declare void @llvm.nacl.atomic.store.i32(i32, i32*, i32) | |
12 declare i32 @llvm.nacl.atomic.load.i32(i32*, i32) | |
13 | |
14 | |
15 define void @test_near_backward(i32 %iptr, i32 %val) { | |
16 entry: | |
17 br label %next | |
18 next: | |
19 %ptr = inttoptr i32 %iptr to i32* | |
20 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
21 br label %next2 | |
22 next2: | |
23 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
24 %cmp = icmp ult i32 %val, 0 | |
25 br i1 %cmp, label %next2, label %next | |
26 } | |
27 | |
28 ; CHECK-LABEL: test_near_backward | |
29 ; CHECK: 8: {{.*}} mov dword ptr | |
30 ; CHECK-NEXT: a: {{.*}} mfence | |
31 ; CHECK-NEXT: d: {{.*}} mov dword ptr | |
32 ; CHECK-NEXT: f: {{.*}} mfence | |
33 ; CHECK-NEXT: 12: {{.*}} cmp | |
34 ; (0x15 + 2) - 10 == 0xd | |
35 ; CHECK-NEXT: 15: 72 f6 jb -10 | |
36 ; (0x17 + 2) - 17 == 0x8 | |
37 ; CHECK-NEXT: 17: eb ef jmp -17 | |
38 | |
39 ; Test one of the backward branches being too large for 8 bits | |
40 ; and one being just okay. | |
41 define void @test_far_backward1(i32 %iptr, i32 %val) { | |
42 entry: | |
43 br label %next | |
44 next: | |
45 %ptr = inttoptr i32 %iptr to i32* | |
46 %tmp = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | |
47 br label %next2 | |
48 next2: | |
49 call void @llvm.nacl.atomic.store.i32(i32 %tmp, i32* %ptr, i32 6) | |
50 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
51 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
52 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
53 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
54 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
55 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
56 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
57 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
58 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
59 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
60 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
61 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
62 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
63 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
64 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
65 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
66 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
67 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
68 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
69 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
70 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
71 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
72 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
73 %cmp = icmp ugt i32 %val, 0 | |
74 br i1 %cmp, label %next2, label %next | |
75 } | |
76 | |
77 ; CHECK-LABEL: test_far_backward1 | |
78 ; CHECK: 8: {{.*}} mov {{.*}}, dword ptr [e{{[^s]}} | |
79 ; CHECK-NEXT: a: {{.*}} mov dword ptr | |
80 ; CHECK-NEXT: c: {{.*}} mfence | |
81 ; (0x85 + 2) - 125 == 0xa | |
82 ; CHECK: 85: 77 83 ja -125 | |
83 ; (0x87 + 5) - 132 == 0x8 | |
84 ; CHECK-NEXT: 87: e9 7c ff ff ff jmp -132 | |
85 | |
86 ; Same as test_far_backward1, but with the conditional branch being | |
87 ; the one that is too far. | |
88 define void @test_far_backward2(i32 %iptr, i32 %val) { | |
89 entry: | |
90 br label %next | |
91 next: | |
92 %ptr = inttoptr i32 %iptr to i32* | |
93 %tmp = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | |
94 %tmp2 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | |
95 %tmp3 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | |
96 %tmp4 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | |
97 %tmp5 = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6) | |
98 br label %next2 | |
99 next2: | |
100 call void @llvm.nacl.atomic.store.i32(i32 %tmp, i32* %ptr, i32 6) | |
101 call void @llvm.nacl.atomic.store.i32(i32 %tmp2, i32* %ptr, i32 6) | |
102 call void @llvm.nacl.atomic.store.i32(i32 %tmp3, i32* %ptr, i32 6) | |
103 call void @llvm.nacl.atomic.store.i32(i32 %tmp4, i32* %ptr, i32 6) | |
104 call void @llvm.nacl.atomic.store.i32(i32 %tmp5, i32* %ptr, i32 6) | |
105 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
106 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
107 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
108 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
109 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
110 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
111 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
112 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
113 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
114 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
115 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
116 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
117 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
118 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
119 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
120 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
121 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
122 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
123 %cmp = icmp sle i32 %val, 0 | |
124 br i1 %cmp, label %next, label %next2 | |
125 } | |
126 | |
127 ; CHECK-LABEL: test_far_backward2 | |
128 ; CHECK: c: {{.*}} mov {{.*}}, dword ptr [e{{[^s]}} | |
129 ; CHECK: 14: {{.*}} mov {{.*}}, dword ptr | |
130 ; CHECK-NEXT: 16: {{.*}} mov dword ptr | |
131 ; CHECK-NEXT: 18: {{.*}} mfence | |
132 ; (0x8c + 6) - 134 == 0xc | |
133 ; CHECK: 8c: 0f 8e 7a ff ff ff jle -134 | |
134 ; (0x92 + 2) - 126 == 0x16 | |
135 ; CHECK-NEXT: 92: eb 82 jmp -126 | |
136 | |
137 define void @test_near_forward(i32 %iptr, i32 %val) { | |
138 entry: | |
139 br label %next1 | |
140 next1: | |
141 %ptr = inttoptr i32 %iptr to i32* | |
142 %cmp = icmp ult i32 %val, 0 | |
143 br i1 %cmp, label %next3, label %next2 | |
144 next2: | |
145 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
146 br label %next3 | |
147 next3: | |
148 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
149 br label %next1 | |
150 } | |
151 ; Forward branches for non-local labels currently use the fully relaxed | |
152 ; form to avoid needing a relaxation pass. | |
153 ; CHECK-LABEL: test_near_forward | |
154 ; CHECK: 8: {{.*}} cmp | |
155 ; CHECK-NEXT: b: 0f 82 05 00 00 00 jb 5 | |
156 ; CHECK-NEXT: 11: {{.*}} mov dword ptr | |
157 ; CHECK-NEXT: 13: {{.*}} mfence | |
158 ; Forward branch is 5 bytes ahead to here. | |
159 ; CHECK-NEXT: 16: {{.*}} mov dword ptr | |
160 ; Jumps back to (0x1b + 2) - 21 == 0x8 (to before the forward branch, | |
161 ; therefore knowing that the forward branch was indeed 6 bytes). | |
162 ; CHECK: 1b: eb eb jmp -21 | |
163 | |
164 | |
165 ; Unlike forward branches to cfg nodes, "local" forward branches | |
Jim Stichnoth
2014/10/22 18:01:14
Can you add a test for a "local" backward branch?
jvoung (off chromium)
2014/10/22 20:43:58
Done.
| |
166 ; always use a 1 byte displacement. | |
167 ; Check local forward branches, followed by a near backward branch | |
168 ; to make sure that the instruction size accounting for the forward | |
169 ; branches are correct, by the time the backward branch is hit. | |
170 ; A 64-bit compare happens to use local forward branches. | |
171 define void @test_local_forward_then_back(i64 %val64, i32 %iptr, i32 %val) { | |
172 entry: | |
173 br label %next | |
174 next: | |
175 %ptr = inttoptr i32 %iptr to i32* | |
176 call void @llvm.nacl.atomic.store.i32(i32 %val, i32* %ptr, i32 6) | |
177 br label %next2 | |
178 next2: | |
179 %cmp = icmp ult i64 %val64, 0 | |
180 br i1 %cmp, label %next, label %next2 | |
181 } | |
182 ; CHECK-LABEL: test_local_forward_then_back | |
183 ; CHECK: 14: {{.*}} mov dword ptr | |
184 ; CHECK-NEXT: 16: {{.*}} mfence | |
185 ; CHECK-NEXT: 19: {{.*}} mov dword ptr {{.*}}, 1 | |
186 ; CHECK-NEXT: 20: {{.*}} cmp | |
187 ; CHECK-NEXT: 23: {{.*}} jb 14 | |
188 ; (0x37 + 2) - 37 == 0x14 | |
189 ; CHECK: 37: {{.*}} jne -37 | |
190 ; (0x39 + 2) - 34 == 0x19 | |
191 ; CHECK: 39: {{.*}} jmp -34 | |
192 | |
193 ; ERRORS-NOT: ICE translation error | |
OLD | NEW |