| # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6 |
| # RUN: llc -mtriple=x86_64-unknown-linux-gnu --run-pass=livevars,twoaddressinstruction %s -o - | FileCheck %s |
| |
| # Positive case: IMUL32rm with %1 as a tied source should be hoisted |
| # before the pass, subreg_to_reg kills a 32-bit vreg (%1) and writes to |
| # physical $eax, which allows IMUL32rm can use %eax. |
| --- |
| name: subreg_to_reg_kill_hoist |
| tracksRegLiveness: true |
| registers: |
| - { id: 0, class: gr64 } |
| - { id: 1, class: gr32 } |
| - { id: 2, class: gr32 } |
| liveins: |
| - { reg: '$rdi', virtual-reg: '%0' } |
| - { reg: '$esi', virtual-reg: '%1' } |
| body: | |
| bb.0: |
| liveins: $rdi, $esi |
| |
| ; CHECK-LABEL: name: subreg_to_reg_kill_hoist |
| ; CHECK: [[COPY1:%[0-9]+]]:gr32 = COPY killed $esi |
| ; CHECK-NEXT: dead $rax = SUBREG_TO_REG [[COPY1]], %subreg.sub_32bit |
| ; CHECK: IMUL32rm |
| %0:gr64 = COPY killed $rdi |
| %1:gr32 = COPY killed $esi |
| dead %2:gr32 = IMUL32rm %1, %0, 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from `ptr undef`, align 4) |
| dead $rax = SUBREG_TO_REG killed %1, %subreg.sub_32bit |
| RET 0 |
| |
| --- |
| # Negative case: subreg_to_reg with a vreg is not hoisted. |
| # The pass keeps the IMUL32rm as is and MOV32rm + IMUL32rr is emitted instead. |
| name: subreg_to_reg_virtual_dst_no_hoist |
| tracksRegLiveness: true |
| registers: |
| - { id: 0, class: gr64 } |
| - { id: 1, class: gr32 } |
| - { id: 2, class: gr32 } |
| - { id: 3, class: gr64 } |
| liveins: |
| - { reg: '$rdi', virtual-reg: '%0' } |
| - { reg: '$esi', virtual-reg: '%1' } |
| body: | |
| bb.0: |
| liveins: $rdi, $esi |
| |
| ; CHECK-LABEL: name: subreg_to_reg_virtual_dst_no_hoist |
| ; CHECK: MOV32rm |
| ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY |
| ; CHECK-NEXT: dead [[COPY2]]:gr32 = IMUL32rr [[COPY2]], %1, implicit-def dead $eflags |
| %0:gr64 = COPY killed $rdi |
| %1:gr32 = COPY killed $esi |
| dead %2:gr32 = IMUL32rm %1, %0, 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from `ptr undef`, align 4) |
| dead %3:gr64 = SUBREG_TO_REG killed %1, %subreg.sub_32bit |
| RET 0 |
| |
| --- |
| # Positive case: COPY to a physical register is hoisted above IMUL32rm. |
| name: copy_kill_hoist |
| tracksRegLiveness: true |
| registers: |
| - { id: 0, class: gr64 } |
| - { id: 1, class: gr32 } |
| - { id: 2, class: gr32 } |
| liveins: |
| - { reg: '$rdi', virtual-reg: '%0' } |
| - { reg: '$esi', virtual-reg: '%1' } |
| body: | |
| bb.0: |
| liveins: $rdi, $esi |
| |
| ; CHECK-LABEL: name: copy_kill_hoist |
| ; CHECK: [[COPY1:%[0-9]+]]:gr32 = COPY killed $esi |
| ; CHECK-NEXT: dead $eax = COPY [[COPY1]] |
| ; CHECK: IMUL32rm |
| %0:gr64 = COPY killed $rdi |
| %1:gr32 = COPY killed $esi |
| dead %2:gr32 = IMUL32rm %1, %0, 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from `ptr undef`, align 4) |
| dead $eax = COPY killed %1 |
| RET 0 |
| |
| --- |
| # Negative case: COPY with a vreg destination is not hoisted. |
| name: copy_virtual_dst_no_hoist |
| tracksRegLiveness: true |
| registers: |
| - { id: 0, class: gr64 } |
| - { id: 1, class: gr32 } |
| - { id: 2, class: gr32 } |
| - { id: 3, class: gr32 } |
| liveins: |
| - { reg: '$rdi', virtual-reg: '%0' } |
| - { reg: '$esi', virtual-reg: '%1' } |
| body: | |
| bb.0: |
| liveins: $rdi, $esi |
| |
| ; CHECK-LABEL: name: copy_virtual_dst_no_hoist |
| ; CHECK: MOV32rm |
| ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY |
| ; CHECK-NEXT: dead [[COPY2]]:gr32 = IMUL32rr [[COPY2]], %1, implicit-def dead $eflags |
| %0:gr64 = COPY killed $rdi |
| %1:gr32 = COPY killed $esi |
| dead %2:gr32 = IMUL32rm %1, %0, 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from `ptr undef`, align 4) |
| dead %3:gr32 = COPY killed %1 |
| RET 0 |
| ... |