1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
| # 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
...
|