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 |
11 declare void @call_target() | 11 declare void @call_target() |
12 declare void @call_target1(i32 %arg0) | 12 declare void @call_target1(i32 %arg0) |
13 declare void @call_target2(i32 %arg0, i32 %arg1) | 13 declare void @call_target2(i32 %arg0, i32 %arg1) |
14 declare void @call_target3(i32 %arg0, i32 %arg1, i32 %arg2) | 14 declare void @call_target3(i32 %arg0, i32 %arg1, i32 %arg2) |
15 @global_short = internal global [2 x i8] zeroinitializer | 15 @global_short = internal global [2 x i8] zeroinitializer |
16 | 16 |
17 ; A direct call sequence uses the right mask and register-call sequence. | 17 ; A direct call sequence uses the right mask and register-call sequence. |
18 define internal void @test_direct_call() { | 18 define internal void @test_direct_call() { |
19 entry: | 19 entry: |
20 call void @call_target() | 20 call void @call_target() |
21 ; bundle aigned. | 21 ; bundle aigned. |
22 | |
23 call void @call_target() | |
24 ret void | 22 ret void |
25 } | 23 } |
26 | 24 |
27 ; CHECK-LABEL:<test_direct_call>: | 25 ; CHECK-LABEL:<test_direct_call>: |
28 ; Search for bundle alignment of first call. | 26 ; Search for bundle alignment of first call. |
29 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 27 ; CHECK: {{[0-9a-f]*}}c: {{.*}} bl {{.*}} call_target |
30 ; CHECK-NEXT: movw [[REG:r[0-9]]], {{.+}} call_target | |
31 ; CHECK-NEXT: movt [[REG]], {{.+}} call_target | |
32 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc000000f | |
33 ; CHECK-NEXT: blx [[REG]] | |
34 ; CHECK-NEXT: {{[0-9a-f]*}}0: | |
35 | 28 |
36 ; Same as above, but force bundle padding by adding three (branch) instruction | 29 ; Same as above, but force bundle padding by adding three (branch) instruction |
37 ; before the tested call. | 30 ; before the tested call. |
38 define internal void @test_direct_call_with_padding_1() { | 31 define internal void @test_direct_call_with_padding_1() { |
39 entry: | 32 entry: |
40 call void @call_target() | 33 call void @call_target() |
41 ; bundle aigned. | 34 ; bundle aigned. |
42 | 35 |
43 br label %next1 ; add 1 inst. | 36 br label %next1 ; add 1 inst. |
44 next1: | 37 next1: |
45 br label %next2 ; add 1 inst. | 38 br label %next2 ; add 1 inst. |
46 next2: | 39 next2: |
47 br label %next3 ; add 1 inst. | |
48 next3: | |
49 call void @call_target() | 40 call void @call_target() |
50 ret void | 41 ret void |
51 } | 42 } |
52 ; CHECK-LABEL:<test_direct_call_with_padding_1>: | 43 ; CHECK-LABEL:<test_direct_call_with_padding_1>: |
53 ; Search for bundle alignment of first call. | 44 ; Search for bundle alignment of first call. |
54 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 45 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
55 ; CHECK-NEXT: b | 46 ; CHECK-NEXT: b |
56 ; CHECK-NEXT: b | 47 ; CHECK-NEXT: b |
57 ; CHECK-NEXT: b | |
58 ; CHECK-NEXT: movw [[REG:r[0-9]]], {{.+}} call_target | |
59 ; CHECK-NEXT: movt [[REG]], {{.+}} call_target | |
60 ; CHECK-NEXT: nop | 48 ; CHECK-NEXT: nop |
61 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc000000f | 49 ; CHECK-NEXT: bl {{.*}} call_target |
62 ; CHECK-NEXT: blx r0 | |
63 ; CHECK-NEXT: {{[0-9a-f]*}}0: | 50 ; CHECK-NEXT: {{[0-9a-f]*}}0: |
64 | 51 |
65 ; Same as above, but force bundle padding by adding two (branch) instruction | 52 ; Same as above, but force bundle padding by adding two (branch) instruction |
66 ; before the tested call. | 53 ; before the tested call. |
67 define internal void @test_direct_call_with_padding_2() { | 54 define internal void @test_direct_call_with_padding_2() { |
68 entry: | 55 entry: |
69 call void @call_target() | 56 call void @call_target() |
70 ; bundle aigned. | 57 ; bundle aigned. |
71 | 58 |
72 br label %next1 ; add 1 inst. | 59 br label %next1 ; add 1 inst. |
73 next1: | 60 next1: |
74 br label %next2 ; add 1 inst. | |
75 next2: | |
76 call void @call_target() | 61 call void @call_target() |
77 ret void | 62 ret void |
78 } | 63 } |
79 | 64 |
80 ; CHECK-LABEL:<test_direct_call_with_padding_2>: | 65 ; CHECK-LABEL:<test_direct_call_with_padding_2>: |
81 ; Search for bundle alignment of first call. | 66 ; Search for bundle alignment of first call. |
82 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 67 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
83 ; CHECK-NEXT: b | 68 ; CHECK-NEXT: b |
84 ; CHECK-NEXT: b | |
85 ; CHECK-NEXT: movw [[REG:r[0-9]]], {{.+}} call_target | |
86 ; CHECK-NEXT: movt [[REG]], {{.+}} call_target | |
87 ; CHECK-NEXT: nop | 69 ; CHECK-NEXT: nop |
88 ; CHECK-NEXT: nop | 70 ; CHECK-NEXT: nop |
89 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc000000f | 71 ; CHECK-NEXT: bl {{.*}} call_target |
90 ; CHECK-NEXT: blx r0 | |
91 ; CHECK-NEXT: {{[0-9a-f]*}}0: | 72 ; CHECK-NEXT: {{[0-9a-f]*}}0: |
92 | 73 |
93 ; Same as above, but force bundle padding by adding single (branch) instruction | 74 ; Same as above, but force bundle padding by adding single (branch) instruction |
94 ; before the tested call. | 75 ; before the tested call. |
95 define internal void @test_direct_call_with_padding_3() { | 76 define internal void @test_direct_call_with_padding_3() { |
96 entry: | 77 entry: |
97 call void @call_target() | 78 call void @call_target() |
98 ; bundle aigned. | 79 ; bundle aigned. |
99 | 80 |
100 br label %next ; add 1 inst. | |
101 next: | |
102 call void @call_target() | 81 call void @call_target() |
103 ret void | 82 ret void |
104 } | 83 } |
105 | 84 |
106 ; CHECK-LABEL:<test_direct_call_with_padding_3>: | 85 ; CHECK-LABEL:<test_direct_call_with_padding_3>: |
107 ; Search for bundle alignment of first call. | 86 ; Search for bundle alignment of first call. |
108 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 87 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
109 ; CHECK-NEXT: b | |
110 ; CHECK-NEXT: movw [[REG:r[0-9]]], {{.+}} call_target | |
111 ; CHECK-NEXT: movt [[REG]], {{.+}} call_target | |
112 ; CHECK-NEXT: nop | 88 ; CHECK-NEXT: nop |
113 ; CHECK-NEXT: nop | 89 ; CHECK-NEXT: nop |
114 ; CHECK-NEXT: nop | 90 ; CHECK-NEXT: nop |
115 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc000000f | 91 ; CHECK-NEXT: bl {{.*}} call_target |
116 ; CHECK-NEXT: blx r0 | |
117 ; CHECK-NEXT: {{[0-9a-f]*}}0: | 92 ; CHECK-NEXT: {{[0-9a-f]*}}0: |
118 | 93 |
119 ; An indirect call sequence uses the right mask and register-call sequence. | 94 ; An indirect call sequence uses the right mask and register-call sequence. |
120 define internal void @test_indirect_call(i32 %target) { | 95 define internal void @test_indirect_call(i32 %target) { |
121 entry: | 96 entry: |
122 %__1 = inttoptr i32 %target to void ()* | 97 %__1 = inttoptr i32 %target to void ()* |
123 call void @call_target(); | 98 call void @call_target(); |
124 ; bundle aigned. | 99 ; bundle aigned. |
125 | 100 |
126 br label %next ; add 1 inst. | 101 br label %next ; add 1 inst. |
127 next: | 102 next: |
128 call void %__1() ; requires 3 insts. | 103 call void %__1() ; requires 3 insts. |
129 ret void | 104 ret void |
130 } | 105 } |
131 | 106 |
132 ; CHECK-LABEL:<test_indirect_call>: | 107 ; CHECK-LABEL:<test_indirect_call>: |
133 ; Search for bundle alignment of first call. | 108 ; Search for bundle alignment of first call. |
134 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 109 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
135 ; CHECK-NEXT: b | 110 ; CHECK-NEXT: b |
136 ; CHECK-NEXT: ldr | 111 ; CHECK-NEXT: ldr |
137 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f | 112 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f |
138 ; CHECK-NEXT: blx [[REG]] | 113 ; CHECK-NEXT: blx [[REG]] |
139 ; CHECK-NEXT: {{[0-9]+}}0: | 114 ; CHECK-NEXT: {{[0-9]+}}0: |
140 | 115 |
141 ; An indirect call sequence uses the right mask and register-call sequence. | 116 ; An indirect call sequence uses the right mask and register-call sequence. |
142 ; Forces bundling before the tested call. | 117 ; Forces bundling before the tested call. |
143 define internal void @test_indirect_call_with_padding_1(i32 %target) { | 118 define internal void @test_indirect_call_with_padding_1(i32 %target) { |
144 entry: | 119 entry: |
145 %__1 = inttoptr i32 %target to void ()* | 120 %__1 = inttoptr i32 %target to void ()* |
146 call void @call_target(); | 121 call void @call_target(); |
147 ; bundle aigned. | 122 ; bundle aigned. |
148 call void %__1() ; requires 3 insts. | 123 call void %__1() ; requires 3 insts. |
149 ret void | 124 ret void |
150 } | 125 } |
151 | 126 |
152 ; CHECK-LABEL: <test_indirect_call_with_padding_1>: | 127 ; CHECK-LABEL: <test_indirect_call_with_padding_1>: |
153 ; Search for bundle alignment of first call. | 128 ; Search for bundle alignment of first call. |
154 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 129 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
155 ; CHECK-NEXT: ldr | 130 ; CHECK-NEXT: ldr |
156 ; CHECK-NEXT: nop | 131 ; CHECK-NEXT: nop |
157 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f | 132 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f |
158 ; CHECK-NEXT: blx [[REG]] | 133 ; CHECK-NEXT: blx [[REG]] |
159 ; CHECK-NEXT: {{[0-9]+}}0: | 134 ; CHECK-NEXT: {{[0-9]+}}0: |
160 | 135 |
161 ; An indirect call sequence uses the right mask and register-call sequence. | 136 ; An indirect call sequence uses the right mask and register-call sequence. |
162 ; Forces bundling by adding three (branch) instructions befor the tested call. | 137 ; Forces bundling by adding three (branch) instructions befor the tested call. |
163 define internal void @test_indirect_call_with_padding_2(i32 %target) { | 138 define internal void @test_indirect_call_with_padding_2(i32 %target) { |
164 entry: | 139 entry: |
165 %__1 = inttoptr i32 %target to void ()* | 140 %__1 = inttoptr i32 %target to void ()* |
166 call void @call_target(); | 141 call void @call_target(); |
167 ; bundle aigned. | 142 ; bundle aigned. |
168 | 143 |
169 br label %next1 ; add 1 inst. | 144 br label %next1 ; add 1 inst. |
170 next1: | 145 next1: |
171 br label %next2 ; add 1 inst. | 146 br label %next2 ; add 1 inst. |
172 next2: | 147 next2: |
173 br label %next3 ; add 1 inst. | 148 br label %next3 ; add 1 inst. |
174 next3: | 149 next3: |
175 call void %__1() ; requires 3 insts. | 150 call void %__1() ; requires 3 insts. |
176 ret void | 151 ret void |
177 } | 152 } |
178 | 153 |
179 ; CHECK-LABEL: <test_indirect_call_with_padding_2>: | 154 ; CHECK-LABEL: <test_indirect_call_with_padding_2>: |
180 ; Search for bundle alignment of first call. | 155 ; Search for bundle alignment of first call. |
181 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 156 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
182 ; CHECK-NEXT: b | 157 ; CHECK-NEXT: b |
183 ; CHECK-NEXT: b | 158 ; CHECK-NEXT: b |
184 ; CHECK-NEXT: b | 159 ; CHECK-NEXT: b |
185 ; CHECK-NEXT: ldr | 160 ; CHECK-NEXT: ldr |
186 ; CHECK-NEXT: nop | 161 ; CHECK-NEXT: nop |
187 ; CHECK-NEXT: nop | 162 ; CHECK-NEXT: nop |
188 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f | 163 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f |
189 ; CHECK-NEXT: blx [[REG]] | 164 ; CHECK-NEXT: blx [[REG]] |
190 ; CHECK-NEXT: {{[0-9]+}}0: | 165 ; CHECK-NEXT: {{[0-9]+}}0: |
191 | 166 |
192 ; An indirect call sequence uses the right mask and register-call sequence. | 167 ; An indirect call sequence uses the right mask and register-call sequence. |
193 ; Forces bundling by adding two (branch) instructions befor the tested call. | 168 ; Forces bundling by adding two (branch) instructions befor the tested call. |
194 define internal void @test_indirect_call_with_padding_3(i32 %target) { | 169 define internal void @test_indirect_call_with_padding_3(i32 %target) { |
195 entry: | 170 entry: |
196 %__1 = inttoptr i32 %target to void ()* | 171 %__1 = inttoptr i32 %target to void ()* |
197 call void @call_target(); | 172 call void @call_target(); |
198 ; bundle aigned. | 173 ; bundle aigned. |
199 | 174 |
200 br label %next1 ; add 1 inst | 175 br label %next1 ; add 1 inst |
201 next1: | 176 next1: |
202 br label %next2 ; add 1 inst | 177 br label %next2 ; add 1 inst |
203 next2: | 178 next2: |
204 call void %__1() ; requires 3 insts. | 179 call void %__1() ; requires 3 insts. |
205 ret void | 180 ret void |
206 } | 181 } |
207 ; CHECK-LABEL: <test_indirect_call_with_padding_3>: | 182 ; CHECK-LABEL: <test_indirect_call_with_padding_3>: |
208 ; Search for bundle alignment of first call. | 183 ; Search for bundle alignment of first call. |
209 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 184 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
210 ; CHECK-NEXT: b | 185 ; CHECK-NEXT: b |
211 ; CHECK-NEXT: b | 186 ; CHECK-NEXT: b |
212 ; CHECK-NEXT: ldr | 187 ; CHECK-NEXT: ldr |
213 ; CHECK-NEXT: nop | 188 ; CHECK-NEXT: nop |
214 ; CHECK-NEXT: nop | 189 ; CHECK-NEXT: nop |
215 ; CHECK-NEXT: nop | 190 ; CHECK-NEXT: nop |
216 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f | 191 ; CHECK-NEXT: bic [[REG:r[0-3]]], [[REG]], {{.*}} 0xc000000f |
217 ; CHECK-NEXT: blx [[REG]] | 192 ; CHECK-NEXT: blx [[REG]] |
218 ; CHECK-NEXT: {{[0-9]+}}0: | 193 ; CHECK-NEXT: {{[0-9]+}}0: |
219 | 194 |
220 ; A return sequences uses the right pop / mask / jmp sequence. | 195 ; A return sequences uses the right pop / mask / jmp sequence. |
221 define internal void @test_ret() { | 196 define internal void @test_ret() { |
222 entry: | 197 entry: |
223 call void @call_target() | 198 call void @call_target() |
224 ; Bundle boundary. | 199 ; Bundle boundary. |
225 br label %next ; add 1 inst. | 200 br label %next ; add 1 inst. |
226 next: | 201 next: |
227 ret void | 202 ret void |
228 } | 203 } |
229 ; CHECK-LABEL:<test_ret>: | 204 ; CHECK-LABEL:<test_ret>: |
230 ; Search for bundle alignment of first call. | 205 ; Search for bundle alignment of first call. |
231 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 206 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
232 ; CHECK-NEXT: b | 207 ; CHECK-NEXT: b |
233 ; CHECK-NEXT: add sp, sp | 208 ; CHECK-NEXT: add sp, sp |
234 ; CHECK-NEXT: bic sp, sp, {{.+}} ; 0xc0000000 | 209 ; CHECK-NEXT: bic sp, sp, {{.+}} ; 0xc0000000 |
235 ; CHECK-NEXT: pop {lr} | 210 ; CHECK-NEXT: pop {lr} |
236 ; CHECK-NEXT: {{[0-9a-f]*}}0: {{.+}} bic lr, lr, {{.+}} ; 0xc000000f | 211 ; CHECK-NEXT: {{[0-9a-f]*}}0: {{.+}} bic lr, lr, {{.+}} ; 0xc000000f |
237 ; CHECK-NEXT: bx lr | 212 ; CHECK-NEXT: bx lr |
238 | 213 |
239 ; A return sequence with padding for bundle lock. | 214 ; A return sequence with padding for bundle lock. |
240 define internal void @test_ret_with_padding() { | 215 define internal void @test_ret_with_padding() { |
241 call void @call_target() | 216 call void @call_target() |
242 ; Bundle boundary. | 217 ; Bundle boundary. |
243 ret void | 218 ret void |
244 } | 219 } |
245 | 220 |
246 ; CHECK-LABEL:<test_ret_with_padding>: | 221 ; CHECK-LABEL:<test_ret_with_padding>: |
247 ; Search for bundle alignment of first call. | 222 ; Search for bundle alignment of first call. |
248 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 223 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
249 ; CHECK-NEXT: add sp, sp | 224 ; CHECK-NEXT: add sp, sp |
250 ; CHECK-NEXT: bic sp, sp, {{.+}} ; 0xc0000000 | 225 ; CHECK-NEXT: bic sp, sp, {{.+}} ; 0xc0000000 |
251 ; CHECK-NEXT: pop {lr} | 226 ; CHECK-NEXT: pop {lr} |
252 ; CHECK-NEXT: nop | 227 ; CHECK-NEXT: nop |
253 ; CHECK-NEXT: {{[0-9a-f]*}}0: {{.+}} bic lr, lr, {{.+}} ; 0xc000000f | 228 ; CHECK-NEXT: {{[0-9a-f]*}}0: {{.+}} bic lr, lr, {{.+}} ; 0xc000000f |
254 ; CHECK-NEXT: bx lr | 229 ; CHECK-NEXT: bx lr |
255 | 230 |
256 ; Store without bundle padding. | 231 ; Store without bundle padding. |
257 define internal void @test_store() { | 232 define internal void @test_store() { |
258 entry: | 233 entry: |
259 call void @call_target() | 234 call void @call_target() |
260 ; Bundle boundary | 235 ; Bundle boundary |
261 store i16 1, i16* undef, align 1 ; 3 insts + bic. | 236 store i16 1, i16* undef, align 1 ; 3 insts + bic. |
262 ret void | 237 ret void |
263 } | 238 } |
264 | 239 |
265 ; CHECK-LABEL: test_store | 240 ; CHECK-LABEL: test_store |
266 ; Search for call at end of bundle. | 241 ; Search for call at end of bundle. |
267 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 242 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
268 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 | 243 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 |
269 ; CHECK-NEXT: mov | 244 ; CHECK-NEXT: mov |
270 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 | 245 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 |
271 ; CHECK-NEXT: strh r{{.+}}[[REG]] | 246 ; CHECK-NEXT: strh r{{.+}}[[REG]] |
272 | 247 |
273 ; Store with bundle padding. Force padding by adding a single branch | 248 ; Store with bundle padding. Force padding by adding a single branch |
274 ; instruction. | 249 ; instruction. |
275 define internal void @test_store_with_padding() { | 250 define internal void @test_store_with_padding() { |
276 entry: | 251 entry: |
277 call void @call_target() | 252 call void @call_target() |
278 ; bundle boundary | 253 ; bundle boundary |
279 br label %next ; add 1 inst. | 254 br label %next ; add 1 inst. |
280 next: | 255 next: |
281 store i16 0, i16* undef, align 1 ; 3 insts | 256 store i16 0, i16* undef, align 1 ; 3 insts |
282 ret void | 257 ret void |
283 } | 258 } |
284 ; CHECK-LABEL: test_store_with_padding | 259 ; CHECK-LABEL: test_store_with_padding |
285 ; Search for call at end of bundle. | 260 ; Search for call at end of bundle. |
286 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 261 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
287 ; CHECK-NEXT: b | 262 ; CHECK-NEXT: b |
288 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 | 263 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 |
289 ; CHECK-NEXT: mov | 264 ; CHECK-NEXT: mov |
290 ; CHECK-NEXT: nop | 265 ; CHECK-NEXT: nop |
291 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 | 266 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 |
292 ; CHECK-NEXT: strh r{{.+}}[[REG]] | 267 ; CHECK-NEXT: strh r{{.+}}[[REG]] |
293 | 268 |
294 | 269 |
295 ; Store without bundle padding. | 270 ; Store without bundle padding. |
296 define internal i32 @test_load() { | 271 define internal i32 @test_load() { |
297 entry: | 272 entry: |
298 call void @call_target() | 273 call void @call_target() |
299 ; Bundle boundary | 274 ; Bundle boundary |
300 %v = load i32, i32* undef, align 1 ; 4 insts, bundling middle 2. | 275 %v = load i32, i32* undef, align 1 ; 4 insts, bundling middle 2. |
301 ret i32 %v | 276 ret i32 %v |
302 } | 277 } |
303 | 278 |
304 ; CHECK-LABEL: test_load | 279 ; CHECK-LABEL: test_load |
305 ; Search for call at end of bundle. | 280 ; Search for call at end of bundle. |
306 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 281 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
307 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 | 282 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 |
308 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 | 283 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 |
309 ; CHECK-NEXT: ldr r{{.+}}[[REG]] | 284 ; CHECK-NEXT: ldr r{{.+}}[[REG]] |
310 | 285 |
311 ; Store with bundle padding. | 286 ; Store with bundle padding. |
312 define internal i32 @test_load_with_padding() { | 287 define internal i32 @test_load_with_padding() { |
313 entry: | 288 entry: |
314 call void @call_target() | 289 call void @call_target() |
315 ; Bundle boundary | 290 ; Bundle boundary |
316 br label %next1 ; add 1 inst. | 291 br label %next1 ; add 1 inst. |
317 next1: | 292 next1: |
318 br label %next2 ; add 1 inst. | 293 br label %next2 ; add 1 inst. |
319 next2: | 294 next2: |
320 %v = load i32, i32* undef, align 1 ; 4 insts, bundling middle 2. | 295 %v = load i32, i32* undef, align 1 ; 4 insts, bundling middle 2. |
321 ret i32 %v | 296 ret i32 %v |
322 } | 297 } |
323 | 298 |
324 ; CHECK-LABEL: test_load_with_padding | 299 ; CHECK-LABEL: test_load_with_padding |
325 ; Search for call at end of bundle. | 300 ; Search for call at end of bundle. |
326 ; CHECK: {{[0-9a-f]*}}c: {{.+}} blx | 301 ; CHECK: {{[0-9a-f]*}}c: {{.+}} bl |
327 ; CHECK-NEXT: b | 302 ; CHECK-NEXT: b |
328 ; CHECK-NEXT: b | 303 ; CHECK-NEXT: b |
329 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 | 304 ; CHECK-NEXT: mov [[REG:r[0-9]]], #0 |
330 ; CHECK-NEXT: nop | 305 ; CHECK-NEXT: nop |
331 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 | 306 ; CHECK-NEXT: bic [[REG]], [[REG]], {{.+}} ; 0xc0000000 |
332 ; CHECK-NEXT: ldr r{{.+}}[[REG]] | 307 ; CHECK-NEXT: ldr r{{.+}}[[REG]] |
OLD | NEW |