2016-07-14 04:36:03 +08:00
|
|
|
# RUN: llc -march=x86 -run-pass machine-cp -verify-machineinstrs -o - %s | FileCheck %s
|
2016-02-25 03:21:48 +08:00
|
|
|
|
|
|
|
--- |
|
|
|
|
declare void @foo()
|
|
|
|
define void @copyprop_remove_kill0() { ret void }
|
|
|
|
define void @copyprop_remove_kill1() { ret void }
|
|
|
|
define void @copyprop_remove_kill2() { ret void }
|
2016-02-26 11:18:50 +08:00
|
|
|
define void @copyprop0() { ret void }
|
2016-02-26 11:18:55 +08:00
|
|
|
define void @copyprop1() { ret void }
|
|
|
|
define void @copyprop2() { ret void }
|
2016-02-26 11:18:50 +08:00
|
|
|
define void @nocopyprop0() { ret void }
|
|
|
|
define void @nocopyprop1() { ret void }
|
2016-02-26 11:18:55 +08:00
|
|
|
define void @nocopyprop2() { ret void }
|
|
|
|
define void @nocopyprop3() { ret void }
|
|
|
|
define void @nocopyprop4() { ret void }
|
|
|
|
define void @nocopyprop5() { ret void }
|
2016-02-25 03:21:48 +08:00
|
|
|
...
|
|
|
|
---
|
2016-02-26 11:18:50 +08:00
|
|
|
# The second copy is redundant and will be removed, check that we also remove
|
2016-02-25 03:21:48 +08:00
|
|
|
# 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
|
|
|
|
...
|
|
|
|
---
|
2016-02-26 11:18:50 +08:00
|
|
|
# The second copy is redundant and will be removed, check that we also remove
|
2016-02-25 03:21:48 +08:00
|
|
|
# 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
|
|
|
|
...
|
|
|
|
---
|
2016-02-26 11:18:50 +08:00
|
|
|
# The second copy is redundant and will be removed, check that we also remove
|
2016-02-25 03:21:48 +08:00
|
|
|
# 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
|
|
|
|
...
|
2016-02-26 11:18:50 +08:00
|
|
|
---
|
|
|
|
# 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
|
|
|
|
...
|
|
|
|
---
|
2016-02-26 11:18:55 +08:00
|
|
|
# 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
|
|
|
|
...
|
|
|
|
---
|
2016-02-26 11:18:50 +08:00
|
|
|
# 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
|
|
|
|
...
|
2016-02-26 11:18:55 +08:00
|
|
|
---
|
|
|
|
# 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
|
|
|
|
...
|