| # RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass branch-relaxation -aarch64-b-offset-bits=64 -aarch64-tbz-offset-bits=9 -aarch64-cbz-offset-bits=9 %s -o - | FileCheck %s |
| # RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass branch-relaxation -aarch64-tbz-offset-bits=9 -aarch64-cbz-offset-bits=9 %s -o - | FileCheck --check-prefix=INDIRECT %s |
| |
| --- | |
| declare i32 @bar() |
| declare i32 @baz() |
| declare i32 @qux() |
| |
| define void @relax_tbz(i1 zeroext %0) { |
| br i1 %0, label %false_block, label %true_block |
| |
| false_block: ; preds = %1 |
| %2 = call i32 @baz() |
| br label %end |
| |
| end: ; preds = %true_block, %false_block |
| %3 = tail call i32 @qux() |
| ret void |
| |
| true_block: ; preds = %1 |
| %4 = call i32 @bar() |
| br label %end |
| } |
| |
| define void @tbz_hot_to_cold(i1 zeroext %0) { |
| br i1 %0, label %hot_block, label %cold_block |
| |
| hot_block: ; preds = %1 |
| %2 = call i32 @baz() |
| br label %end |
| |
| end: ; preds = %cold_block, %hot_block |
| %3 = tail call i32 @qux() |
| ret void |
| |
| cold_block: ; preds = %1 |
| %4 = call i32 @bar() |
| br label %end |
| } |
| |
| define void @tbz_no_valid_tramp(i1 zeroext %0) { |
| br i1 %0, label %hot, label %cold |
| |
| hot: ; preds = %1 |
| %2 = call i32 @baz() |
| call void asm sideeffect ".space 1024", ""() |
| br label %end |
| |
| end: ; preds = %cold, %hot |
| %3 = tail call i32 @qux() |
| ret void |
| |
| cold: ; preds = %1 |
| %4 = call i32 @bar() |
| br label %end |
| } |
| |
| define void @tbz_cold_to_hot(i1 zeroext %0) { |
| br i1 %0, label %cold_block, label %hot_block |
| |
| cold_block: ; preds = %1 |
| %2 = call i32 @baz() |
| br label %end |
| |
| end: ; preds = %hot_block, %cold_block |
| %3 = tail call i32 @qux() |
| ret void |
| |
| hot_block: ; preds = %1 |
| %4 = call i32 @bar() |
| br label %end |
| } |
| |
| define void @tbz_tramp_pushed_oob(i1 zeroext %0, i1 zeroext %1) { |
| entry: |
| %x16 = call i64 asm sideeffect "mov x16, 1", "={x16}"() |
| br i1 %0, label %unrelaxable, label %cold |
| |
| unrelaxable: ; preds = %entry |
| br i1 %1, label %end, label %cold |
| |
| end: ; preds = %unrelaxable |
| call void asm sideeffect ".space 996", ""() |
| call void asm sideeffect "# reg use $0", "{x16}"(i64 %x16) |
| ret void |
| |
| cold: ; preds = %entry, %unrelaxable |
| call void asm sideeffect "# reg use $0", "{x16}"(i64 %x16) |
| ret void |
| } |
| |
| |
| define void @x16_used_cold_to_hot() { |
| entry: |
| %x16 = call i64 asm sideeffect "mov x16, 1", "={x16}"() |
| %cmp = icmp eq i64 %x16, 0 |
| br i1 %cmp, label %hot, label %cold |
| |
| hot: ; preds = %cold, %entry |
| call void asm sideeffect "# reg use $0", "{x16}"(i64 %x16) |
| ret void |
| |
| cold: ; preds = %entry |
| call void asm sideeffect ".space 4", ""() |
| br label %hot |
| } |
| |
| define void @all_used_cold_to_hot() { |
| entry: |
| %x0 = call i64 asm sideeffect "mov x0, 1", "={x0}"() |
| %x1 = call i64 asm sideeffect "mov x1, 1", "={x1}"() |
| %x2 = call i64 asm sideeffect "mov x2, 1", "={x2}"() |
| %x3 = call i64 asm sideeffect "mov x3, 1", "={x3}"() |
| %x4 = call i64 asm sideeffect "mov x4, 1", "={x4}"() |
| %x5 = call i64 asm sideeffect "mov x5, 1", "={x5}"() |
| %x6 = call i64 asm sideeffect "mov x6, 1", "={x6}"() |
| %x7 = call i64 asm sideeffect "mov x7, 1", "={x7}"() |
| %x8 = call i64 asm sideeffect "mov x8, 1", "={x8}"() |
| %x9 = call i64 asm sideeffect "mov x9, 1", "={x9}"() |
| %x10 = call i64 asm sideeffect "mov x10, 1", "={x10}"() |
| %x11 = call i64 asm sideeffect "mov x11, 1", "={x11}"() |
| %x12 = call i64 asm sideeffect "mov x12, 1", "={x12}"() |
| %x13 = call i64 asm sideeffect "mov x13, 1", "={x13}"() |
| %x14 = call i64 asm sideeffect "mov x14, 1", "={x14}"() |
| %x15 = call i64 asm sideeffect "mov x15, 1", "={x15}"() |
| %x17 = call i64 asm sideeffect "mov x17, 1", "={x17}"() |
| %x18 = call i64 asm sideeffect "mov x18, 1", "={x18}"() |
| %x19 = call i64 asm sideeffect "mov x19, 1", "={x19}"() |
| %x20 = call i64 asm sideeffect "mov x20, 1", "={x20}"() |
| %x21 = call i64 asm sideeffect "mov x21, 1", "={x21}"() |
| %x22 = call i64 asm sideeffect "mov x22, 1", "={x22}"() |
| %x23 = call i64 asm sideeffect "mov x23, 1", "={x23}"() |
| %x24 = call i64 asm sideeffect "mov x24, 1", "={x24}"() |
| %x25 = call i64 asm sideeffect "mov x25, 1", "={x25}"() |
| %x26 = call i64 asm sideeffect "mov x26, 1", "={x26}"() |
| %x27 = call i64 asm sideeffect "mov x27, 1", "={x27}"() |
| %x28 = call i64 asm sideeffect "mov x28, 1", "={x28}"() |
| br label %cold |
| |
| exit: ; preds = %cold |
| call void asm sideeffect "# reg use $0", "{x0}"(i64 %x0) |
| call void asm sideeffect "# reg use $0", "{x1}"(i64 %x1) |
| call void asm sideeffect "# reg use $0", "{x2}"(i64 %x2) |
| call void asm sideeffect "# reg use $0", "{x3}"(i64 %x3) |
| call void asm sideeffect "# reg use $0", "{x4}"(i64 %x4) |
| call void asm sideeffect "# reg use $0", "{x5}"(i64 %x5) |
| call void asm sideeffect "# reg use $0", "{x6}"(i64 %x6) |
| call void asm sideeffect "# reg use $0", "{x7}"(i64 %x7) |
| call void asm sideeffect "# reg use $0", "{x8}"(i64 %x8) |
| call void asm sideeffect "# reg use $0", "{x9}"(i64 %x9) |
| call void asm sideeffect "# reg use $0", "{x10}"(i64 %x10) |
| call void asm sideeffect "# reg use $0", "{x11}"(i64 %x11) |
| call void asm sideeffect "# reg use $0", "{x12}"(i64 %x12) |
| call void asm sideeffect "# reg use $0", "{x13}"(i64 %x13) |
| call void asm sideeffect "# reg use $0", "{x14}"(i64 %x14) |
| call void asm sideeffect "# reg use $0", "{x15}"(i64 %x15) |
| call void asm sideeffect "# reg use $0", "{x16}"(i64 %x16) |
| call void asm sideeffect "# reg use $0", "{x17}"(i64 %x17) |
| call void asm sideeffect "# reg use $0", "{x18}"(i64 %x18) |
| call void asm sideeffect "# reg use $0", "{x19}"(i64 %x19) |
| call void asm sideeffect "# reg use $0", "{x20}"(i64 %x20) |
| call void asm sideeffect "# reg use $0", "{x21}"(i64 %x21) |
| call void asm sideeffect "# reg use $0", "{x22}"(i64 %x22) |
| call void asm sideeffect "# reg use $0", "{x23}"(i64 %x23) |
| call void asm sideeffect "# reg use $0", "{x24}"(i64 %x24) |
| call void asm sideeffect "# reg use $0", "{x25}"(i64 %x25) |
| call void asm sideeffect "# reg use $0", "{x26}"(i64 %x26) |
| call void asm sideeffect "# reg use $0", "{x27}"(i64 %x27) |
| call void asm sideeffect "# reg use $0", "{x28}"(i64 %x28) |
| ret void |
| |
| cold: ; preds = %entry |
| %x16 = call i64 asm sideeffect "mov x16, 1", "={x16}"() |
| br label %exit |
| } |
| |
| ... |
| --- |
| name: relax_tbz |
| tracksRegLiveness: true |
| liveins: |
| - { reg: '$w0', virtual-reg: '' } |
| stack: |
| - { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16, |
| stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| body: | |
| ; CHECK-LABEL: name: relax_tbz |
| ; COM: Check that cross-section conditional branches are |
| ; COM: relaxed. |
| ; CHECK: bb.0 (%ir-block.1, bbsections 1): |
| ; CHECK-NEXT: successors: %bb.3 |
| ; CHECK: TBNZW |
| ; CHECK-SAME: %bb.3 |
| ; CHECK: B %bb.2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: bb.3 (%ir-block.1, bbsections 1): |
| ; CHECK-NEXT: successors: %bb.1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: B %bb.1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: bb.1.false_block (bbsections 2): |
| ; CHECK: TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: bb.2.true_block (bbsections 3): |
| ; CHECK: TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| bb.0 (%ir-block.1, bbsections 1): |
| successors: %bb.1, %bb.2 |
| liveins: $w0, $lr |
| |
| early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0) |
| TBZW killed renamable $w0, 0, %bb.2 |
| B %bb.1 |
| |
| bb.1.false_block (bbsections 2): |
| BL @baz, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $w0 |
| early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) |
| TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| |
| bb.2.true_block (bbsections 3): |
| BL @bar, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $w0 |
| early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) |
| TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| ... |
| --- |
| name: tbz_hot_to_cold |
| tracksRegLiveness: true |
| liveins: |
| - { reg: '$w0', virtual-reg: '' } |
| stack: |
| - { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16, |
| stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| body: | |
| ; CHECK-LABEL: name: tbz_hot_to_cold |
| ; COM: Check that branch relaxation relaxes cross-section conditional |
| ; COM: branches by creating trampolines after all other hot basic blocks. |
| ; CHECK: bb.0 (%ir-block.1): |
| ; CHECK-NEXT: successors: %bb.1 |
| ; CHECK-SAME: , %bb.3 |
| ; CHECK: TBZW |
| ; CHECK-SAME: %bb.3 |
| ; CHECK: bb.1.hot_block: |
| ; CHECK: TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| ; CHECK: bb.3 (%ir-block.1): |
| ; CHECK-NEXT: successors: %bb.2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: B %bb.2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: bb.2.cold_block (bbsections Cold): |
| ; CHECK: TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| bb.0 (%ir-block.1): |
| successors: %bb.1, %bb.2 |
| liveins: $w0, $lr |
| |
| early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0) |
| TBZW killed renamable $w0, 0, %bb.2 |
| |
| bb.1.hot_block: |
| BL @baz, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $w0 |
| early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) |
| TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| |
| bb.2.cold_block (bbsections Cold): |
| BL @bar, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $w0 |
| early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) |
| TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| |
| ... |
| --- |
| name: tbz_no_valid_tramp |
| tracksRegLiveness: true |
| liveins: |
| - { reg: '$w0', virtual-reg: '' } |
| stack: |
| - { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16, |
| stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| machineFunctionInfo: |
| hasRedZone: false |
| body: | |
| ; CHECK-LABEL: name: tbz_no_valid_tramp |
| ; COM: Check that branch relaxation doesn't insert a trampoline if there is no |
| ; COM: viable insertion location. |
| ; CHECK: bb.0 (%ir-block.1): |
| ; CHECK-NEXT: successors: %bb.1 |
| ; CHECK-SAME: , %bb.3 |
| ; CHECK: CBNZW |
| ; CHECK-SAME: %bb.1 |
| ; CHECK-NEXT: B |
| ; CHECK-SAME: %bb.3 |
| ; CHECK: bb.1.hot: |
| ; CHECK: TCRETURNdi |
| ; CHECK: bb.2.cold (bbsections Cold): |
| ; CHECK: TCRETURNdi |
| bb.0 (%ir-block.1): |
| successors: %bb.1, %bb.2 |
| liveins: $w0, $lr |
| |
| early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0) |
| CBZW killed renamable $w0, %bb.2 |
| |
| bb.1.hot: |
| BL @baz, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $w0 |
| INLINEASM &".space 1024", 1 /* sideeffect attdialect */ |
| early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) |
| TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| |
| bb.2.cold (bbsections Cold): |
| BL @bar, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $w0 |
| early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) |
| TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| |
| ... |
| --- |
| name: tbz_cold_to_hot |
| tracksRegLiveness: true |
| liveins: |
| - { reg: '$w0', virtual-reg: '' } |
| stack: |
| - { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16, |
| stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| machineFunctionInfo: |
| hasRedZone: false |
| body: | |
| ; CHECK-LABEL: name: tbz_cold_to_hot |
| ; COM: Check that relaxation of conditional branches from the Cold section to |
| ; COM: the Hot section doesn't modify the Hot section. |
| ; CHECK: bb.0 (%ir-block.1, bbsections Cold): |
| ; CHECK-NEXT: successors: %bb.1 |
| ; CHECK-SAME: , %bb.2 |
| ; CHECK: CBNZW |
| ; CHECK-SAME: %bb.1 |
| ; CHECK-NEXT: B %bb.2 |
| ; CHECK: bb.1.cold_block (bbsections Cold): |
| ; CHECK: TCRETURNdi |
| ; CHECK: bb.2.hot_block: |
| ; CHECK: TCRETURNdi |
| bb.0 (%ir-block.1, bbsections Cold): |
| successors: %bb.1, %bb.2 |
| liveins: $w0, $lr |
| |
| early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0) |
| CBZW killed renamable $w0, %bb.2 |
| |
| bb.1.cold_block (bbsections Cold): |
| BL @baz, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $w0 |
| early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) |
| TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| |
| bb.2.hot_block: |
| BL @bar, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $w0 |
| early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) |
| TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| |
| ... |
| --- |
| name: tbz_tramp_pushed_oob |
| tracksRegLiveness: true |
| liveins: |
| - { reg: '$w0', virtual-reg: '' } |
| - { reg: '$w1', virtual-reg: '' } |
| stack: |
| - { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16, |
| stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| machineFunctionInfo: |
| hasRedZone: false |
| body: | |
| ; INDIRECT-LABEL: name: tbz_tramp_pushed_oob |
| ; COM: Check that a conditional branch to a trampoline is properly relaxed |
| ; COM: if the trampoline is pushed out of range. |
| ; INDIRECT: bb.0.entry: |
| ; INDIRECT-NEXT: successors: %bb.1 |
| ; INDIRECT-SAME: , %[[TRAMP1:bb.[0-9]+]] |
| ; INDIRECT: TBNZW |
| ; INDIRECT-SAME: %bb.1 |
| ; INDIRECT-NEXT: B{{ }} |
| ; INDIRECT-SAME: %[[TRAMP1]] |
| ; INDIRECT: bb.1.unrelaxable: |
| ; INDIRECT-NEXT: successors: %bb.2 |
| ; INDIRECT-SAME: , %[[TRAMP2:bb.[0-9]+]] |
| ; INDIRECT: TBNZW |
| ; INDIRECT-SAME: %bb.2 |
| ; INDIRECT: [[TRAMP2]] |
| ; INDIRECT-NEXT: successors: %bb.6 |
| ; INDIRECT: bb.2.end: |
| ; INDIRECT: TCRETURNdi |
| ; INDIRECT: [[TRAMP1]].entry: |
| ; INDIRECT-NEXT: successors: %[[TRAMP1_SPILL:bb.[0-9]+]] |
| ; INDIRECT: [[TRAMP1_SPILL]].entry: |
| ; INDIRECT-NEXT: successors: %[[TRAMP1_RESTORE:bb.[0-9]+]] |
| ; INDIRECT: early-clobber $sp = STRXpre $[[SPILL_REGISTER:x[0-9]+]], $sp, -16 |
| ; INDIRECT-NEXT: B %[[TRAMP1_RESTORE:bb.[0-9]+]] |
| ; INDIRECT: [[TRAMP1_RESTORE]].cold (bbsections Cold): |
| ; INDIRECT-NEXT: successors: %bb.3 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: early-clobber $sp, $[[SPILL_REGISTER]] = LDRXpost $sp, 16 |
| ; INDIRECT: bb.3.cold (bbsections Cold): |
| ; INDIRECT: TCRETURNdi |
| |
| bb.0.entry (%ir-block.entry): |
| successors: %bb.1, %bb.3 |
| liveins: $w0, $w1, $lr |
| |
| early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0) |
| INLINEASM &"mov x16, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x16 |
| TBZW killed renamable $w0, 0, %bb.3 |
| |
| bb.1.unrelaxable: |
| successors: %bb.2, %bb.3 |
| liveins: $w1, $x16 |
| |
| TBNZW killed renamable $w1, 0, %bb.2 |
| |
| B %bb.3 |
| |
| bb.2.end: |
| liveins: $x16 |
| |
| INLINEASM &".space 996", 1 /* sideeffect attdialect */ |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x16 |
| early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) |
| TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| |
| bb.3.cold (bbsections Cold): |
| liveins: $x16 |
| |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x16 |
| early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) |
| TCRETURNdi @qux, 0, csr_aarch64_aapcs, implicit $sp |
| |
| ... |
| |
| name: x16_used_cold_to_hot |
| tracksRegLiveness: true |
| liveins: [] |
| machineFunctionInfo: |
| hasRedZone: false |
| body: | |
| ; INDIRECT-LABEL: name: x16_used_cold_to_hot |
| ; COM: Check that unconditional branches from the cold section to |
| ; COM: the hot section manually insert indirect branches if x16 |
| ; COM: isn't available but there is still a free register. |
| ; INDIRECT: bb.0.entry: |
| ; INDIRECT-NEXT: successors: %bb.1 |
| ; INDIRECT-SAME: , %bb.3 |
| ; INDIRECT: TBZW killed renamable $w8, 0, %bb.1 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: bb.3.entry: |
| ; INDIRECT-NEXT: successors: %bb.4 |
| ; INDIRECT-NEXT: liveins: $x16 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: early-clobber $sp = STRXpre $[[SPILL_REGISTER]], $sp, -16 |
| ; INDIRECT-NEXT: B %bb.4 |
| ; INDIRECT: bb.1.hot: |
| ; INDIRECT-NEXT: liveins: $x16 |
| ; INDIRECT: killed $x16 |
| ; INDIRECT: RET undef $lr |
| ; INDIRECT: bb.4.cold (bbsections Cold): |
| ; INDIRECT-NEXT: successors: %bb.2 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: early-clobber $sp, $[[SPILL_REGISTER]] = LDRXpost $sp, 16 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: bb.2.cold (bbsections Cold): |
| ; INDIRECT-NEXT: successors: %bb.5 |
| ; INDIRECT-NEXT: liveins: $x16 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: INLINEASM &".space 4", 1 /* sideeffect attdialect */ |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: bb.5.cold (bbsections Cold): |
| ; INDIRECT-NEXT: successors: %bb.1 |
| ; INDIRECT-NEXT: liveins: $x16 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: $[[SCAVENGED_REGISTER:x[0-9]+]] = ADRP target-flags(aarch64-page) <mcsymbol .LBB5_1> |
| ; INDIRECT-NEXT: $[[SCAVENGED_REGISTER]] = ADDXri $[[SCAVENGED_REGISTER]], target-flags(aarch64-pageoff, aarch64-nc) <mcsymbol .LBB5_1>, 0 |
| ; INDIRECT-NEXT: BR $[[SCAVENGED_REGISTER]] |
| |
| bb.0.entry: |
| successors: %bb.1, %bb.2 |
| |
| $sp = frame-setup SUBXri $sp, 16, 0 |
| INLINEASM &"mov x16, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x16 |
| dead renamable $x8 = SUBSXri $x16, 0, 0, implicit-def $nzcv |
| renamable $w8 = CSINCWr $wzr, $wzr, 1, implicit killed $nzcv |
| TBZW killed renamable $w8, 0, %bb.1 |
| |
| B %bb.2 |
| |
| bb.1.hot: |
| liveins: $x16 |
| |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x16 |
| $sp = frame-destroy ADDXri $sp, 16, 0 |
| RET undef $lr |
| |
| bb.2.cold (bbsections Cold): |
| successors: %bb.1 |
| liveins: $x16 |
| |
| INLINEASM &".space 4", 1 /* sideeffect attdialect */ |
| B %bb.1 |
| ... |
| --- |
| name: all_used_cold_to_hot |
| tracksRegLiveness: true |
| stack: |
| - { id: 0, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8, |
| stack-id: default, callee-saved-register: '$x19', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| - { id: 1, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, |
| stack-id: default, callee-saved-register: '$x20', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| - { id: 2, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8, |
| stack-id: default, callee-saved-register: '$x21', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| - { id: 3, name: '', type: spill-slot, offset: -32, size: 8, alignment: 8, |
| stack-id: default, callee-saved-register: '$x22', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| - { id: 4, name: '', type: spill-slot, offset: -40, size: 8, alignment: 8, |
| stack-id: default, callee-saved-register: '$x23', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| - { id: 5, name: '', type: spill-slot, offset: -48, size: 8, alignment: 8, |
| stack-id: default, callee-saved-register: '$x24', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| - { id: 6, name: '', type: spill-slot, offset: -56, size: 8, alignment: 8, |
| stack-id: default, callee-saved-register: '$x25', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| - { id: 7, name: '', type: spill-slot, offset: -64, size: 8, alignment: 8, |
| stack-id: default, callee-saved-register: '$x26', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| - { id: 8, name: '', type: spill-slot, offset: -72, size: 8, alignment: 8, |
| stack-id: default, callee-saved-register: '$x27', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| - { id: 9, name: '', type: spill-slot, offset: -80, size: 8, alignment: 8, |
| stack-id: default, callee-saved-register: '$x28', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| - { id: 10, name: '', type: spill-slot, offset: -96, size: 8, alignment: 16, |
| stack-id: default, callee-saved-register: '$fp', callee-saved-restored: true, |
| debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } |
| machineFunctionInfo: |
| hasRedZone: false |
| body: | |
| ; INDIRECT-LABEL: name: all_used_cold_to_hot |
| ; COM: Check that unconditional branches from the cold section to |
| ; COM: the hot section spill x16 and defer indirect branch |
| ; COM: insertion to the linker if there are no free general-purpose |
| ; COM: registers. |
| ; INDIRECT: bb.0.entry: |
| ; INDIRECT-NEXT: successors: %bb.3 |
| ; INDIRECT-NEXT: liveins: $fp, $x27, $x28, $x25, $x26, $x23, $x24, $x21, $x22, $x19, $x20 |
| ; INDIRECT-COUNT-29: INLINEASM &"mov |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT: bb.3.entry: |
| ; INDIRECT-NEXT: successors: %bb.2 |
| ; INDIRECT-NEXT: liveins: $fp, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, |
| ; INDIRECT-SAME: $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x17, $x18, $x19, |
| ; INDIRECT-SAME: $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: B %bb.2 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: bb.1.exit: |
| ; INDIRECT-NEXT: liveins: $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, |
| ; INDIRECT-SAME: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, |
| ; INDIRECT-SAME: $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28, $fp |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-COUNT-30: INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed |
| ; INDIRECT: RET undef $lr |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: bb.6.exit: |
| ; INDIRECT-NEXT: successors: %bb.7(0x80000000) |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: early-clobber $sp, $[[SPILL_REGISTER]] = LDRXpost $sp, 16 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: bb.7.exit: |
| ; INDIRECT-NEXT: successors: %bb.1(0x80000000) |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: B %bb.1 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: bb.2.cold (bbsections Cold): |
| ; INDIRECT-NEXT: successors: %bb.5 |
| ; INDIRECT-NEXT: liveins: $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, |
| ; INDIRECT-SAME: $x10, $x11, $x12, $x13, $x14, $x15, $x17, $x18, $x19, $x20, |
| ; INDIRECT-SAME: $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28, $fp |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: INLINEASM &"mov x16, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x16 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: bb.5.cold (bbsections Cold): |
| ; INDIRECT-NEXT: successors: %bb.6 |
| ; INDIRECT-NEXT: liveins: $fp, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, |
| ; INDIRECT-SAME: $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, |
| ; INDIRECT-SAME: $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28 |
| ; INDIRECT-NEXT: {{ $}} |
| ; INDIRECT-NEXT: early-clobber $sp = STRXpre $[[SPILL_REGISTER]], $sp, -16 |
| ; INDIRECT-NEXT: B %bb.6 |
| |
| bb.0.entry: |
| successors: %bb.2 |
| liveins: $fp, $x27, $x28, $x25, $x26, $x23, $x24, $x21, $x22, $x19, $x20 |
| |
| $sp = frame-setup SUBXri $sp, 112, 0 |
| frame-setup STRXui killed $fp, $sp, 2 :: (store (s64) into %stack.10) |
| frame-setup STPXi killed $x28, killed $x27, $sp, 4 :: (store (s64) into %stack.9), (store (s64) into %stack.8) |
| frame-setup STPXi killed $x26, killed $x25, $sp, 6 :: (store (s64) into %stack.7), (store (s64) into %stack.6) |
| frame-setup STPXi killed $x24, killed $x23, $sp, 8 :: (store (s64) into %stack.5), (store (s64) into %stack.4) |
| frame-setup STPXi killed $x22, killed $x21, $sp, 10 :: (store (s64) into %stack.3), (store (s64) into %stack.2) |
| frame-setup STPXi killed $x20, killed $x19, $sp, 12 :: (store (s64) into %stack.1), (store (s64) into %stack.0) |
| INLINEASM &"mov x0, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x0 |
| INLINEASM &"mov x1, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x1 |
| INLINEASM &"mov x2, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x2 |
| INLINEASM &"mov x3, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x3 |
| INLINEASM &"mov x4, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x4 |
| INLINEASM &"mov x5, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x5 |
| INLINEASM &"mov x6, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x6 |
| INLINEASM &"mov x7, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x7 |
| INLINEASM &"mov x8, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x8 |
| INLINEASM &"mov x9, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x9 |
| INLINEASM &"mov x10, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x10 |
| INLINEASM &"mov x11, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x11 |
| INLINEASM &"mov x12, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x12 |
| INLINEASM &"mov x13, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x13 |
| INLINEASM &"mov x14, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x14 |
| INLINEASM &"mov x15, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x15 |
| INLINEASM &"mov x17, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x17 |
| INLINEASM &"mov x18, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x18 |
| INLINEASM &"mov x19, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x19 |
| INLINEASM &"mov x20, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x20 |
| INLINEASM &"mov x21, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x21 |
| INLINEASM &"mov x22, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x22 |
| INLINEASM &"mov x23, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x23 |
| INLINEASM &"mov x24, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x24 |
| INLINEASM &"mov x25, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x25 |
| INLINEASM &"mov x26, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x26 |
| INLINEASM &"mov x27, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x27 |
| INLINEASM &"mov x28, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x28 |
| INLINEASM &"mov fp, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $fp |
| B %bb.2 |
| |
| |
| bb.1.exit: |
| liveins: $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28, $fp |
| |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x0 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x1 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x2 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x3 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x4 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x5 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x6 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x7 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x8 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x9 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x10 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x11 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x12 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x13 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x14 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x15 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x16 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x17 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x18 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x19 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x20 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x21 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x22 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x23 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x24 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x25 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x26 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x27 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $x28 |
| INLINEASM &"# reg use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, killed $fp |
| $x20, $x19 = frame-destroy LDPXi $sp, 12 :: (load (s64) from %stack.1), (load (s64) from %stack.0) |
| $x22, $x21 = frame-destroy LDPXi $sp, 10 :: (load (s64) from %stack.3), (load (s64) from %stack.2) |
| $x24, $x23 = frame-destroy LDPXi $sp, 8 :: (load (s64) from %stack.5), (load (s64) from %stack.4) |
| $x26, $x25 = frame-destroy LDPXi $sp, 6 :: (load (s64) from %stack.7), (load (s64) from %stack.6) |
| $x28, $x27 = frame-destroy LDPXi $sp, 4 :: (load (s64) from %stack.9), (load (s64) from %stack.8) |
| $fp = frame-destroy LDRXui $sp, 2 :: (load (s64) from %stack.10) |
| $sp = frame-destroy ADDXri $sp, 112, 0 |
| RET undef $lr |
| |
| bb.2.cold (bbsections Cold): |
| successors: %bb.1 |
| liveins: $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x17, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28, $fp |
| |
| INLINEASM &"mov x16, 1", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $x16 |
| B %bb.1 |
| |
| ... |