| # RUN: llc -mtriple=i686-- -run-pass machine-cp -verify-machineinstrs -o - %s | FileCheck %s |
| |
| --- | |
| declare void @foo() |
| define void @copyprop_remove_kill0() { ret void } |
| define void @copyprop_remove_kill1() { ret void } |
| define void @copyprop_remove_kill2() { ret void } |
| define void @copyprop0() { ret void } |
| define void @copyprop1() { ret void } |
| define void @copyprop2() { ret void } |
| define void @nocopyprop0() { ret void } |
| define void @nocopyprop1() { ret void } |
| define void @nocopyprop2() { ret void } |
| define void @nocopyprop3() { ret void } |
| define void @nocopyprop4() { ret void } |
| define void @nocopyprop5() { ret void } |
| ... |
| --- |
| # The second copy is redundant and will be removed, check that we also remove |
| # the kill flag of intermediate instructions. |
| # CHECK-LABEL: name: copyprop_remove_kill0 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rax = COPY %rdi |
| # CHECK-NEXT: NOOP implicit %rdi |
| # CHECK-NOT: COPY |
| # CHECK-NEXT: NOOP implicit %rax, implicit %rdi |
| name: copyprop_remove_kill0 |
| body: | |
| bb.0: |
| %rax = COPY %rdi |
| NOOP implicit killed %rdi |
| %rdi = COPY %rax |
| NOOP implicit %rax, implicit %rdi |
| ... |
| --- |
| # The second copy is redundant and will be removed, check that we also remove |
| # the kill flag of intermediate instructions. |
| # CHECK-LABEL: name: copyprop_remove_kill1 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rax = COPY %rdi |
| # CHECK-NEXT: NOOP implicit %edi |
| # CHECK-NOT: COPY |
| # CHECK-NEXT: NOOP implicit %rax, implicit %rdi |
| name: copyprop_remove_kill1 |
| body: | |
| bb.0: |
| %rax = COPY %rdi |
| NOOP implicit killed %edi |
| %rdi = COPY %rax |
| NOOP implicit %rax, implicit %rdi |
| ... |
| --- |
| # The second copy is redundant and will be removed, check that we also remove |
| # the kill flag of intermediate instructions. |
| # CHECK-LABEL: name: copyprop_remove_kill2 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %ax = COPY %di |
| # CHECK-NEXT: NOOP implicit %rdi |
| # CHECK-NOT: COPY |
| # CHECK-NEXT: NOOP implicit %rax, implicit %rdi |
| name: copyprop_remove_kill2 |
| body: | |
| bb.0: |
| %ax = COPY %di |
| NOOP implicit killed %rdi |
| %di = COPY %ax |
| NOOP implicit %rax, implicit %rdi |
| ... |
| --- |
| # The second copy is redundant; the call preserves the source and dest register. |
| # CHECK-LABEL: name: copyprop0 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rax = COPY %rdi |
| # CHECK-NEXT: CALL64pcrel32 @foo, csr_64_rt_mostregs |
| # CHECK-NEXT: NOOP implicit %edi |
| # CHECK-NOT: COPY |
| # CHECK-NEXT: NOOP implicit %rax, implicit %rdi |
| name: copyprop0 |
| body: | |
| bb.0: |
| %rax = COPY %rdi |
| CALL64pcrel32 @foo, csr_64_rt_mostregs |
| NOOP implicit killed %edi |
| %rdi = COPY %rax |
| NOOP implicit %rax, implicit %rdi |
| ... |
| --- |
| # The 2nd copy is redundant; The call preserves the source and dest register. |
| # CHECK-LABEL: name: copyprop1 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rax = COPY %rdi |
| # CHECK-NEXT: NOOP implicit %rax |
| # CHECK-NEXT: NOOP implicit %rax, implicit %rdi |
| name: copyprop1 |
| body: | |
| bb.0: |
| %rax = COPY %rdi |
| NOOP implicit killed %rax |
| %rax = COPY %rdi |
| NOOP implicit %rax, implicit %rdi |
| ... |
| --- |
| # CHECK-LABEL: name: copyprop2 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rax = COPY %rdi |
| # CHECK-NEXT: NOOP implicit %ax |
| # CHECK-NEXT: CALL64pcrel32 @foo, csr_64_rt_mostregs |
| # CHECK-NOT: %rax = COPY %rdi |
| # CHECK-NEXT: NOOP implicit %rax, implicit %rdi |
| name: copyprop2 |
| body: | |
| bb.0: |
| %rax = COPY %rdi |
| NOOP implicit killed %ax |
| CALL64pcrel32 @foo, csr_64_rt_mostregs |
| %rax = COPY %rdi |
| NOOP implicit %rax, implicit %rdi |
| ... |
| --- |
| # The second copy is not redundant if the source register (%rax) is clobbered |
| # even if the dest (%rbp) is not. |
| # CHECK-LABEL: name: nocopyprop0 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rax = COPY %rbp |
| # CHECK-NEXT: CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp |
| # CHECK-NEXT: %rbp = COPY %rax |
| # CHECK-NEXT: NOOP implicit %rax, implicit %rbp |
| name: nocopyprop0 |
| body: | |
| bb.0: |
| %rax = COPY %rbp |
| CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp |
| %rbp = COPY %rax |
| NOOP implicit %rax, implicit %rbp |
| ... |
| --- |
| # The second copy is not redundant if the dest register (%rax) is clobbered |
| # even if the source (%rbp) is not. |
| # CHECK-LABEL: name: nocopyprop1 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rbp = COPY %rax |
| # CHECK-NEXT: CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp |
| # CHECK-NEXT: %rax = COPY %rbp |
| # CHECK-NEXT: NOOP implicit %rax, implicit %rbp |
| name: nocopyprop1 |
| body: | |
| bb.0: |
| %rbp = COPY %rax |
| CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp |
| %rax = COPY %rbp |
| NOOP implicit %rax, implicit %rbp |
| ... |
| --- |
| # The second copy is not redundant if the source register (%rax) is clobbered |
| # even if the dest (%rbp) is not. |
| # CHECK-LABEL: name: nocopyprop2 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rax = COPY %rbp |
| # CHECK-NEXT: CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp |
| # CHECK-NEXT: %rax = COPY %rbp |
| # CHECK-NEXT: NOOP implicit %rax, implicit %rbp |
| name: nocopyprop2 |
| body: | |
| bb.0: |
| %rax = COPY %rbp |
| CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp |
| %rax = COPY %rbp |
| NOOP implicit %rax, implicit %rbp |
| ... |
| --- |
| # The second copy is not redundant if the dest register (%rax) is clobbered |
| # even if the source (%rbp) is not. |
| # CHECK-LABEL: name: nocopyprop3 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rbp = COPY %rax |
| # CHECK-NEXT: CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp |
| # CHECK-NEXT: %rbp = COPY %rax |
| # CHECK-NEXT: NOOP implicit %rax, implicit %rbp |
| name: nocopyprop3 |
| body: | |
| bb.0: |
| %rbp = COPY %rax |
| CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp |
| %rbp = COPY %rax |
| NOOP implicit %rax, implicit %rbp |
| ... |
| --- |
| # A reserved register may change its value so the 2nd copy is not redundant. |
| # CHECK-LABEL: name: nocopyprop4 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rax = COPY %rip |
| # CHECK-NEXT: NOOP implicit %rax |
| # CHECK-NEXT: %rax = COPY %rip |
| # CHECK-NEXT: NOOP implicit %rax |
| name: nocopyprop4 |
| body: | |
| bb.0: |
| %rax = COPY %rip |
| NOOP implicit %rax |
| %rax = COPY %rip |
| NOOP implicit %rax |
| ... |
| --- |
| # Writing to a reserved register may have additional effects (slightly illegal |
| # testcase because writing to %rip like this should make the instruction a jump) |
| # CHECK-LABEL: name: nocopyprop5 |
| # CHECK: bb.0: |
| # CHECK-NEXT: %rip = COPY %rax |
| # CHECK-NEXT: %rip = COPY %rax |
| name: nocopyprop5 |
| body: | |
| bb.0: |
| %rip = COPY %rax |
| %rip = COPY %rax |
| ... |