1# RUN: llc -march=x86 -run-pass machine-cp -verify-machineinstrs -o - %s | FileCheck %s
2
3--- |
4  declare void @foo()
5  define void @copyprop_remove_kill0() { ret void }
6  define void @copyprop_remove_kill1() { ret void }
7  define void @copyprop_remove_kill2() { ret void }
8  define void @copyprop0() { ret void }
9  define void @copyprop1() { ret void }
10  define void @copyprop2() { ret void }
11  define void @nocopyprop0() { ret void }
12  define void @nocopyprop1() { ret void }
13  define void @nocopyprop2() { ret void }
14  define void @nocopyprop3() { ret void }
15  define void @nocopyprop4() { ret void }
16  define void @nocopyprop5() { ret void }
17...
18---
19# The second copy is redundant and will be removed, check that we also remove
20# the kill flag of intermediate instructions.
21# CHECK-LABEL: name: copyprop_remove_kill0
22# CHECK: bb.0:
23# CHECK-NEXT: %rax = COPY %rdi
24# CHECK-NEXT: NOOP implicit %rdi
25# CHECK-NOT: COPY
26# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
27name: copyprop_remove_kill0
28allVRegsAllocated: true
29body: |
30  bb.0:
31    %rax = COPY %rdi
32    NOOP implicit killed %rdi
33    %rdi = COPY %rax
34    NOOP implicit %rax, implicit %rdi
35...
36---
37# The second copy is redundant and will be removed, check that we also remove
38# the kill flag of intermediate instructions.
39# CHECK-LABEL: name: copyprop_remove_kill1
40# CHECK: bb.0:
41# CHECK-NEXT: %rax = COPY %rdi
42# CHECK-NEXT: NOOP implicit %edi
43# CHECK-NOT: COPY
44# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
45name: copyprop_remove_kill1
46allVRegsAllocated: true
47body: |
48  bb.0:
49    %rax = COPY %rdi
50    NOOP implicit killed %edi
51    %rdi = COPY %rax
52    NOOP implicit %rax, implicit %rdi
53...
54---
55# The second copy is redundant and will be removed, check that we also remove
56# the kill flag of intermediate instructions.
57# CHECK-LABEL: name: copyprop_remove_kill2
58# CHECK: bb.0:
59# CHECK-NEXT: %ax = COPY %di
60# CHECK-NEXT: NOOP implicit %rdi
61# CHECK-NOT: COPY
62# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
63name: copyprop_remove_kill2
64allVRegsAllocated: true
65body: |
66  bb.0:
67    %ax = COPY %di
68    NOOP implicit killed %rdi
69    %di = COPY %ax
70    NOOP implicit %rax, implicit %rdi
71...
72---
73# The second copy is redundant; the call preserves the source and dest register.
74# CHECK-LABEL: name: copyprop0
75# CHECK: bb.0:
76# CHECK-NEXT: %rax = COPY %rdi
77# CHECK-NEXT: CALL64pcrel32 @foo, csr_64_rt_mostregs
78# CHECK-NEXT: NOOP implicit %edi
79# CHECK-NOT: COPY
80# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
81name: copyprop0
82allVRegsAllocated: true
83body: |
84  bb.0:
85    %rax = COPY %rdi
86    CALL64pcrel32 @foo, csr_64_rt_mostregs
87    NOOP implicit killed %edi
88    %rdi = COPY %rax
89    NOOP implicit %rax, implicit %rdi
90...
91---
92# The 2nd copy is redundant; The call preserves the source and dest register.
93# CHECK-LABEL: name: copyprop1
94# CHECK: bb.0:
95# CHECK-NEXT: %rax = COPY %rdi
96# CHECK-NEXT: NOOP implicit %rax
97# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
98name: copyprop1
99allVRegsAllocated: true
100body: |
101  bb.0:
102    %rax = COPY %rdi
103    NOOP implicit killed %rax
104    %rax = COPY %rdi
105    NOOP implicit %rax, implicit %rdi
106...
107---
108# CHECK-LABEL: name: copyprop2
109# CHECK: bb.0:
110# CHECK-NEXT: %rax = COPY %rdi
111# CHECK-NEXT: NOOP implicit %ax
112# CHECK-NEXT: CALL64pcrel32 @foo, csr_64_rt_mostregs
113# CHECK-NOT: %rax = COPY %rdi
114# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
115name: copyprop2
116allVRegsAllocated: true
117body: |
118  bb.0:
119    %rax = COPY %rdi
120    NOOP implicit killed %ax
121    CALL64pcrel32 @foo, csr_64_rt_mostregs
122    %rax = COPY %rdi
123    NOOP implicit %rax, implicit %rdi
124...
125---
126# The second copy is not redundant if the source register (%rax) is clobbered
127# even if the dest (%rbp) is not.
128# CHECK-LABEL: name: nocopyprop0
129# CHECK: bb.0:
130# CHECK-NEXT: %rax = COPY %rbp
131# CHECK-NEXT: CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp
132# CHECK-NEXT: %rbp = COPY %rax
133# CHECK-NEXT: NOOP implicit %rax, implicit %rbp
134name: nocopyprop0
135allVRegsAllocated: true
136body: |
137  bb.0:
138    %rax = COPY %rbp
139    CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp
140    %rbp = COPY %rax
141    NOOP implicit %rax, implicit %rbp
142...
143---
144# The second copy is not redundant if the dest register (%rax) is clobbered
145# even if the source (%rbp) is not.
146# CHECK-LABEL: name: nocopyprop1
147# CHECK: bb.0:
148# CHECK-NEXT: %rbp = COPY %rax
149# CHECK-NEXT: CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp
150# CHECK-NEXT: %rax = COPY %rbp
151# CHECK-NEXT: NOOP implicit %rax, implicit %rbp
152name: nocopyprop1
153allVRegsAllocated: true
154body: |
155  bb.0:
156    %rbp = COPY %rax
157    CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp
158    %rax = COPY %rbp
159    NOOP implicit %rax, implicit %rbp
160...
161---
162# The second copy is not redundant if the source register (%rax) is clobbered
163# even if the dest (%rbp) is not.
164# CHECK-LABEL: name: nocopyprop2
165# CHECK: bb.0:
166# CHECK-NEXT: %rax = COPY %rbp
167# CHECK-NEXT: CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp
168# CHECK-NEXT: %rax = COPY %rbp
169# CHECK-NEXT: NOOP implicit %rax, implicit %rbp
170name: nocopyprop2
171allVRegsAllocated: true
172body: |
173  bb.0:
174    %rax = COPY %rbp
175    CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp
176    %rax = COPY %rbp
177    NOOP implicit %rax, implicit %rbp
178...
179---
180# The second copy is not redundant if the dest register (%rax) is clobbered
181# even if the source (%rbp) is not.
182# CHECK-LABEL: name: nocopyprop3
183# CHECK: bb.0:
184# CHECK-NEXT: %rbp = COPY %rax
185# CHECK-NEXT: CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp
186# CHECK-NEXT: %rbp = COPY %rax
187# CHECK-NEXT: NOOP implicit %rax, implicit %rbp
188name: nocopyprop3
189allVRegsAllocated: true
190body: |
191  bb.0:
192    %rbp = COPY %rax
193    CALL64pcrel32 @foo, csr_64, implicit %rax, implicit %rbp
194    %rbp = COPY %rax
195    NOOP implicit %rax, implicit %rbp
196...
197---
198# A reserved register may change its value so the 2nd copy is not redundant.
199# CHECK-LABEL: name: nocopyprop4
200# CHECK: bb.0:
201# CHECK-NEXT: %rax = COPY %rip
202# CHECK-NEXT: NOOP implicit %rax
203# CHECK-NEXT: %rax = COPY %rip
204# CHECK-NEXT: NOOP implicit %rax
205name: nocopyprop4
206allVRegsAllocated: true
207body: |
208  bb.0:
209    %rax = COPY %rip
210    NOOP implicit %rax
211    %rax = COPY %rip
212    NOOP implicit %rax
213...
214---
215# Writing to a reserved register may have additional effects (slightly illegal
216# testcase because writing to %rip like this should make the instruction a jump)
217# CHECK-LABEL: name: nocopyprop5
218# CHECK: bb.0:
219# CHECK-NEXT: %rip = COPY %rax
220# CHECK-NEXT: %rip = COPY %rax
221name: nocopyprop5
222allVRegsAllocated: true
223body: |
224  bb.0:
225    %rip = COPY %rax
226    %rip = COPY %rax
227...
228