| 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 |