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 declare i32 @llvm.nacl.atomic.rmw.i32(i32, i32*, i32, i32) |
| 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 |
| 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 |
| 194 ; Test that backward local branches also work and are small. |
| 195 ; Some of the atomic instructions use a cmpxchg loop. |
| 196 define void @test_local_backward(i64 %val64, i32 %iptr, i32 %val) { |
| 197 entry: |
| 198 br label %next |
| 199 next: |
| 200 %ptr = inttoptr i32 %iptr to i32* |
| 201 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 5, i32* %ptr, i32 %val, i32 6) |
| 202 br label %next2 |
| 203 next2: |
| 204 %success = icmp eq i32 1, %a |
| 205 br i1 %success, label %next, label %next2 |
| 206 } |
| 207 ; CHECK-LABEL: test_local_backward |
| 208 ; CHECK: 9: {{.*}} mov {{.*}}, dword |
| 209 ; CHECK: b: {{.*}} mov |
| 210 ; CHECK-NEXT: d: {{.*}} xor |
| 211 ; CHECK-NEXT: f: {{.*}} lock |
| 212 ; CHECK-NEXT: 10: {{.*}} cmpxchg |
| 213 ; (0x13 + 2) - 10 == 0xb |
| 214 ; CHECK-NEXT: 13: 75 f6 jne -10 |
| 215 ; (0x1c + 2) - 21 == 0x9 |
| 216 ; CHECK: 1c: 74 eb je -21 |
| 217 |
| 218 ; ERRORS-NOT: ICE translation error |
OLD | NEW |