OLD | NEW |
1 ; Tests basics and corner cases of arm32 sandboxing, using -Om1 in the hope that | 1 ; Tests basics and corner cases of arm32 sandboxing, using -Om1 in the hope that |
2 ; the output will remain stable. When packing bundles, we try to limit to a few | 2 ; the output will remain stable. When packing bundles, we try to limit to a few |
3 ; instructions with well known sizes and minimal use of registers and stack | 3 ; instructions with well known sizes and minimal use of registers and stack |
4 ; slots in the lowering sequence. | 4 ; slots in the lowering sequence. |
5 | 5 |
6 ; REQUIRES: allow_dump, target_ARM32 | 6 ; REQUIRES: allow_dump, target_ARM32 |
7 ; RUN: %p2i -i %s --sandbox --filetype=asm --target=arm32 --assemble \ | 7 ; RUN: %p2i -i %s --sandbox --filetype=asm --target=arm32 --assemble \ |
8 ; RUN: --disassemble --args -Om1 -allow-externally-defined-symbols \ | 8 ; RUN: --disassemble --args -Om1 -allow-externally-defined-symbols \ |
9 ; RUN: -ffunction-sections -reg-use r0,r1,r3 | FileCheck %s | 9 ; RUN: -ffunction-sections -reg-use r0,r1,r3 | FileCheck %s |
10 | 10 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 ; Search for bundle alignment of first call. | 53 ; Search for bundle alignment of first call. |
54 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 54 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx |
55 ; CHECK-NEXT: b | 55 ; CHECK-NEXT: b |
56 ; CHECK-NEXT: b | 56 ; CHECK-NEXT: b |
57 ; CHECK-NEXT: b | 57 ; CHECK-NEXT: b |
58 ; CHECK-NEXT: movw [[REG:r[0-9]]], {{.+}} call_target | 58 ; CHECK-NEXT: movw [[REG:r[0-9]]], {{.+}} call_target |
59 ; CHECK-NEXT: movt [[REG]], {{.+}} call_target | 59 ; CHECK-NEXT: movt [[REG]], {{.+}} call_target |
60 ; CHECK-NEXT: nop | 60 ; CHECK-NEXT: nop |
61 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc000000f | 61 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc000000f |
62 ; CHECK-NEXT: blx r0 | 62 ; CHECK-NEXT: blx r0 |
63 ; CHECk-NEXT: {{[0-9a-f]*}}0: | 63 ; CHECK-NEXT: {{[0-9a-f]*}}0: |
64 | 64 |
65 ; Same as above, but force bundle padding by adding two (branch) instruction | 65 ; Same as above, but force bundle padding by adding two (branch) instruction |
66 ; before the tested call. | 66 ; before the tested call. |
67 define internal void @test_direct_call_with_padding_2() { | 67 define internal void @test_direct_call_with_padding_2() { |
68 entry: | 68 entry: |
69 call void @call_target() | 69 call void @call_target() |
70 ; bundle aigned. | 70 ; bundle aigned. |
71 | 71 |
72 br label %next1 ; add 1 inst. | 72 br label %next1 ; add 1 inst. |
73 next1: | 73 next1: |
74 br label %next2 ; add 1 inst. | 74 br label %next2 ; add 1 inst. |
75 next2: | 75 next2: |
76 call void @call_target() | 76 call void @call_target() |
77 ret void | 77 ret void |
78 } | 78 } |
79 | 79 |
80 ; CHECK-LABEL:<test_direct_call_with_padding_2>: | 80 ; CHECK-LABEL:<test_direct_call_with_padding_2>: |
81 ; Search for bundle alignment of first call. | 81 ; Search for bundle alignment of first call. |
82 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 82 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx |
83 ; CHECK-NEXT: b | 83 ; CHECK-NEXT: b |
84 ; CHECK-NEXT: b | 84 ; CHECK-NEXT: b |
85 ; CHECK-NEXT: movw [[REG:r[0-9]]], {{.+}} call_target | 85 ; CHECK-NEXT: movw [[REG:r[0-9]]], {{.+}} call_target |
86 ; CHECK-NEXT: movt [[REG]], {{.+}} call_target | 86 ; CHECK-NEXT: movt [[REG]], {{.+}} call_target |
87 ; CHECK-NEXT: nop | 87 ; CHECK-NEXT: nop |
88 ; CHECK-NEXT: nop | 88 ; CHECK-NEXT: nop |
89 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc000000f | 89 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc000000f |
90 ; CHECK-NEXT: blx r0 | 90 ; CHECK-NEXT: blx r0 |
91 ; CHECk-NEXT: {{[0-9a-f]*}}0: | 91 ; CHECK-NEXT: {{[0-9a-f]*}}0: |
92 | 92 |
93 ; Same as above, but force bundle padding by adding single (branch) instruction | 93 ; Same as above, but force bundle padding by adding single (branch) instruction |
94 ; before the tested call. | 94 ; before the tested call. |
95 define internal void @test_direct_call_with_padding_3() { | 95 define internal void @test_direct_call_with_padding_3() { |
96 entry: | 96 entry: |
97 call void @call_target() | 97 call void @call_target() |
98 ; bundle aigned. | 98 ; bundle aigned. |
99 | 99 |
100 br label %next ; add 1 inst. | 100 br label %next ; add 1 inst. |
101 next: | 101 next: |
102 call void @call_target() | 102 call void @call_target() |
103 ret void | 103 ret void |
104 } | 104 } |
105 | 105 |
106 ; CHECK-LABEL:<test_direct_call_with_padding_3>: | 106 ; CHECK-LABEL:<test_direct_call_with_padding_3>: |
107 ; Search for bundle alignment of first call. | 107 ; Search for bundle alignment of first call. |
108 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 108 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx |
109 ; CHECK-NEXT: b | 109 ; CHECK-NEXT: b |
110 ; CHECK-NEXT: movw [[REG:r[0-9]]], {{.+}} call_target | 110 ; CHECK-NEXT: movw [[REG:r[0-9]]], {{.+}} call_target |
111 ; CHECK-NEXT: movt [[REG]], {{.+}} call_target | 111 ; CHECK-NEXT: movt [[REG]], {{.+}} call_target |
112 ; CHECK-NEXT: nop | 112 ; CHECK-NEXT: nop |
113 ; CHECK-NEXT: nop | 113 ; CHECK-NEXT: nop |
114 ; CHECK-NEXT: nop | 114 ; CHECK-NEXT: nop |
115 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc000000f | 115 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc000000f |
116 ; CHECK-NEXT: blx r0 | 116 ; CHECK-NEXT: blx r0 |
117 ; CHECk-NEXT: {{[0-9a-f]*}}0: | 117 ; CHECK-NEXT: {{[0-9a-f]*}}0: |
118 | 118 |
119 ; An indirect call sequence uses the right mask and register-call sequence. | 119 ; An indirect call sequence uses the right mask and register-call sequence. |
120 define internal void @test_indirect_call(i32 %target) { | 120 define internal void @test_indirect_call(i32 %target) { |
121 entry: | 121 entry: |
122 %__1 = inttoptr i32 %target to void ()* | 122 %__1 = inttoptr i32 %target to void ()* |
123 call void @call_target(); | 123 call void @call_target(); |
124 ; bundle aigned. | 124 ; bundle aigned. |
125 | 125 |
126 br label %next ; add 1 inst. | 126 br label %next ; add 1 inst. |
127 next: | 127 next: |
128 call void %__1() ; requires 3 insts. | 128 call void %__1() ; requires 3 insts. |
129 ret void | 129 ret void |
130 } | 130 } |
131 | 131 |
132 ; CHECK-LABEL:<test_indirect_call>: | 132 ; CHECK-LABEL:<test_indirect_call>: |
133 ; Search for bundle alignment of first call. | 133 ; Search for bundle alignment of first call. |
134 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 134 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx |
135 ; CHECK-NEXT: b | 135 ; CHECK-NEXT: b |
136 ; CHECK-NEXT: ldr | 136 ; CHECK-NEXT: ldr |
137 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f | 137 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f |
138 ; CHECK-NEXT: blx [[REG]] | 138 ; CHECK-NEXT: blx [[REG]] |
139 ; CHECk-NEXT: {{[0-9]+}}0: | 139 ; CHECK-NEXT: {{[0-9]+}}0: |
140 | 140 |
141 ; An indirect call sequence uses the right mask and register-call sequence. | 141 ; An indirect call sequence uses the right mask and register-call sequence. |
142 ; Forces bundling before the tested call. | 142 ; Forces bundling before the tested call. |
143 define internal void @test_indirect_call_with_padding_1(i32 %target) { | 143 define internal void @test_indirect_call_with_padding_1(i32 %target) { |
144 entry: | 144 entry: |
145 %__1 = inttoptr i32 %target to void ()* | 145 %__1 = inttoptr i32 %target to void ()* |
146 call void @call_target(); | 146 call void @call_target(); |
147 ; bundle aigned. | 147 ; bundle aigned. |
148 call void %__1() ; requires 3 insts. | 148 call void %__1() ; requires 3 insts. |
149 ret void | 149 ret void |
150 } | 150 } |
151 | 151 |
152 ; CHECK-LABEL: <test_indirect_call_with_padding_1>: | 152 ; CHECK-LABEL: <test_indirect_call_with_padding_1>: |
153 ; Search for bundle alignment of first call. | 153 ; Search for bundle alignment of first call. |
154 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 154 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx |
155 ; CHECK-NEXT: ldr | 155 ; CHECK-NEXT: ldr |
156 ; CHECK-NEXT: nop | 156 ; CHECK-NEXT: nop |
157 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f | 157 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f |
158 ; CHECK-NEXT: blx [[REG]] | 158 ; CHECK-NEXT: blx [[REG]] |
159 ; CHECk-NEXT: {{[0-9]+}}0: | 159 ; CHECK-NEXT: {{[0-9]+}}0: |
160 | 160 |
161 ; An indirect call sequence uses the right mask and register-call sequence. | 161 ; An indirect call sequence uses the right mask and register-call sequence. |
162 ; Forces bundling by adding three (branch) instructions befor the tested call. | 162 ; Forces bundling by adding three (branch) instructions befor the tested call. |
163 define internal void @test_indirect_call_with_padding_2(i32 %target) { | 163 define internal void @test_indirect_call_with_padding_2(i32 %target) { |
164 entry: | 164 entry: |
165 %__1 = inttoptr i32 %target to void ()* | 165 %__1 = inttoptr i32 %target to void ()* |
166 call void @call_target(); | 166 call void @call_target(); |
167 ; bundle aigned. | 167 ; bundle aigned. |
168 | 168 |
169 br label %next1 ; add 1 inst. | 169 br label %next1 ; add 1 inst. |
(...skipping 10 matching lines...) Expand all Loading... |
180 ; Search for bundle alignment of first call. | 180 ; Search for bundle alignment of first call. |
181 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 181 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx |
182 ; CHECK-NEXT: b | 182 ; CHECK-NEXT: b |
183 ; CHECK-NEXT: b | 183 ; CHECK-NEXT: b |
184 ; CHECK-NEXT: b | 184 ; CHECK-NEXT: b |
185 ; CHECK-NEXT: ldr | 185 ; CHECK-NEXT: ldr |
186 ; CHECK-NEXT: nop | 186 ; CHECK-NEXT: nop |
187 ; CHECK-NEXT: nop | 187 ; CHECK-NEXT: nop |
188 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f | 188 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f |
189 ; CHECK-NEXT: blx [[REG]] | 189 ; CHECK-NEXT: blx [[REG]] |
190 ; CHECk-NEXT: {{[0-9]+}}0: | 190 ; CHECK-NEXT: {{[0-9]+}}0: |
191 | 191 |
192 ; An indirect call sequence uses the right mask and register-call sequence. | 192 ; An indirect call sequence uses the right mask and register-call sequence. |
193 ; Forces bundling by adding two (branch) instructions befor the tested call. | 193 ; Forces bundling by adding two (branch) instructions befor the tested call. |
194 define internal void @test_indirect_call_with_padding_3(i32 %target) { | 194 define internal void @test_indirect_call_with_padding_3(i32 %target) { |
195 entry: | 195 entry: |
196 %__1 = inttoptr i32 %target to void ()* | 196 %__1 = inttoptr i32 %target to void ()* |
197 call void @call_target(); | 197 call void @call_target(); |
198 ; bundle aigned. | 198 ; bundle aigned. |
199 | 199 |
200 br label %next1 ; add 1 inst | 200 br label %next1 ; add 1 inst |
201 next1: | 201 next1: |
202 br label %next2 ; add 1 inst | 202 br label %next2 ; add 1 inst |
203 next2: | 203 next2: |
204 call void %__1() ; requires 3 insts. | 204 call void %__1() ; requires 3 insts. |
205 ret void | 205 ret void |
206 } | 206 } |
207 ; CHECK-LABEL: <test_indirect_call_with_padding_3>: | 207 ; CHECK-LABEL: <test_indirect_call_with_padding_3>: |
208 ; Search for bundle alignment of first call. | 208 ; Search for bundle alignment of first call. |
209 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 209 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx |
210 ; CHECK-NEXT: b | 210 ; CHECK-NEXT: b |
211 ; CHECK-NEXT: b | 211 ; CHECK-NEXT: b |
212 ; CHECK-NEXT: ldr | 212 ; CHECK-NEXT: ldr |
213 ; CHECK-NEXT: nop | 213 ; CHECK-NEXT: nop |
214 ; CHECK-NEXT: nop | 214 ; CHECK-NEXT: nop |
215 ; CHECK-NEXT: nop | 215 ; CHECK-NEXT: nop |
216 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f | 216 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f |
217 ; CHECK-NEXT: blx [[REG]] | 217 ; CHECK-NEXT: blx [[REG]] |
218 ; CHECk-NEXT: {{[0-9]+}}0: | 218 ; CHECK-NEXT: {{[0-9]+}}0: |
219 | 219 |
220 ; A return sequences uses the right pop / mask / jmp sequence. | 220 ; A return sequences uses the right pop / mask / jmp sequence. |
221 define internal void @test_ret() { | 221 define internal void @test_ret() { |
222 entry: | 222 entry: |
223 call void @call_target() | 223 call void @call_target() |
224 ; Bundle boundary. | 224 ; Bundle boundary. |
225 br label %next ; add 1 inst. | 225 br label %next ; add 1 inst. |
226 next: | 226 next: |
227 ret void | 227 ret void |
228 } | 228 } |
(...skipping 30 matching lines...) Expand all Loading... |
259 call void @call_target() | 259 call void @call_target() |
260 ; Bundle boundary | 260 ; Bundle boundary |
261 store i16 1, i16* undef, align 1 ; 3 insts + bic. | 261 store i16 1, i16* undef, align 1 ; 3 insts + bic. |
262 ret void | 262 ret void |
263 } | 263 } |
264 | 264 |
265 ; CHECK-LABEL: test_store | 265 ; CHECK-LABEL: test_store |
266 ; Search for call at end of bundle. | 266 ; Search for call at end of bundle. |
267 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 267 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx |
268 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 | 268 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 |
269 ; CHECK-NEXT: mov | 269 ; CHECK-NEXT: mov |
270 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 | 270 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 |
271 ; CHECK-NEXT: strh r{{.+}}[[REG]] | 271 ; CHECK-NEXT: strh r{{.+}}[[REG]] |
272 | 272 |
273 ; Store with bundle padding. Force padding by adding a single branch | 273 ; Store with bundle padding. Force padding by adding a single branch |
274 ; instruction. | 274 ; instruction. |
275 define internal void @test_store_with_padding() { | 275 define internal void @test_store_with_padding() { |
276 entry: | 276 entry: |
277 call void @call_target() | 277 call void @call_target() |
278 ; bundle boundary | 278 ; bundle boundary |
279 br label %next ; add 1 inst. | 279 br label %next ; add 1 inst. |
280 next: | 280 next: |
281 store i16 0, i16* undef, align 1 ; 3 insts | 281 store i16 0, i16* undef, align 1 ; 3 insts |
282 ret void | 282 ret void |
283 } | 283 } |
284 ; CHECK-LABEL: test_store_with_padding | 284 ; CHECK-LABEL: test_store_with_padding |
285 ; Search for call at end of bundle. | 285 ; Search for call at end of bundle. |
286 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 286 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx |
287 ; CHECK-NEXT: b | 287 ; CHECK-NEXT: b |
288 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 | 288 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 |
289 ; CHECK-NEXT: mov | 289 ; CHECK-NEXT: mov |
290 ; CHECK-NEXT: nop | 290 ; CHECK-NEXT: nop |
291 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 | 291 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 |
292 ; CHECK-NEXT: strh r{{.+}}[[REG]] | 292 ; CHECK-NEXT: strh r{{.+}}[[REG]] |
293 | 293 |
294 | 294 |
295 ; Store without bundle padding. | 295 ; Store without bundle padding. |
296 define internal i32 @test_load() { | 296 define internal i32 @test_load() { |
297 entry: | 297 entry: |
298 call void @call_target() | 298 call void @call_target() |
299 ; Bundle boundary | 299 ; Bundle boundary |
(...skipping 23 matching lines...) Expand all Loading... |
323 | 323 |
324 ; CHECK-LABEL: test_load_with_padding | 324 ; CHECK-LABEL: test_load_with_padding |
325 ; Search for call at end of bundle. | 325 ; Search for call at end of bundle. |
326 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 326 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx |
327 ; CHECK-NEXT: b | 327 ; CHECK-NEXT: b |
328 ; CHECK-NEXT: b | 328 ; CHECK-NEXT: b |
329 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 | 329 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 |
330 ; CHECK-NEXT: nop | 330 ; CHECK-NEXT: nop |
331 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 | 331 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 |
332 ; CHECK-NEXT: ldr r{{.+}}[[REG]] | 332 ; CHECK-NEXT: ldr r{{.+}}[[REG]] |
OLD | NEW |