@@ -83,6 +83,27 @@ def as_index(self) -> str:
83
83
terms = self .as_terms ()
84
84
return make_index (terms )
85
85
86
+ def equivalent_to (self , other : "StackOffset" ) -> bool :
87
+ if self .deep == other .deep and self .high == other .high :
88
+ return True
89
+ deep = list (self .deep )
90
+ for x in other .deep :
91
+ try :
92
+ deep .remove (x )
93
+ except ValueError :
94
+ return False
95
+ if deep :
96
+ return False
97
+ high = list (self .high )
98
+ for x in other .high :
99
+ try :
100
+ high .remove (x )
101
+ except ValueError :
102
+ return False
103
+ if high :
104
+ return False
105
+ return True
106
+
86
107
87
108
def make_index (terms : list [tuple [str , str ]]) -> str :
88
109
# Produce an index expression from the terms honoring PEP 8,
@@ -131,9 +152,9 @@ def as_stack_effect(self, lax: bool = False) -> StackEffect:
131
152
132
153
133
154
@dataclasses .dataclass
134
- class CopyEffect :
135
- src : StackEffect
136
- dst : StackEffect
155
+ class CopyItem :
156
+ src : StackItem
157
+ dst : StackItem
137
158
138
159
139
160
class EffectManager :
@@ -143,7 +164,7 @@ class EffectManager:
143
164
active_caches : list [ActiveCacheEffect ]
144
165
peeks : list [StackItem ]
145
166
pokes : list [StackItem ]
146
- copies : list [CopyEffect ] # See merge()
167
+ copies : list [CopyItem ] # See merge()
147
168
# Track offsets from stack pointer
148
169
min_offset : StackOffset
149
170
final_offset : StackOffset
@@ -179,16 +200,18 @@ def __init__(
179
200
while (
180
201
pred .pokes
181
202
and self .peeks
182
- and pred .pokes [- 1 ].effect == self .peeks [- 1 ].effect
203
+ and pred .pokes [- 1 ].effect == self .peeks [0 ].effect
183
204
):
184
- src = pred .pokes .pop (- 1 ).effect
185
- dst = self .peeks .pop (0 ).effect
186
- pred .final_offset .deeper (src )
187
- if dst .name != UNUSED :
188
- destinations .add (dst .name )
189
- if dst .name != src .name :
190
- sources .add (src .name )
191
- self .copies .append (CopyEffect (src , dst ))
205
+ src = pred .pokes .pop (- 1 )
206
+ dst = self .peeks .pop (0 )
207
+ assert src .offset .equivalent_to (dst .offset ), (src , dst )
208
+ pred .final_offset .deeper (src .effect )
209
+ if dst .effect .name != src .effect .name :
210
+ if dst .effect .name != UNUSED :
211
+ destinations .add (dst .effect .name )
212
+ if src .effect .name != UNUSED :
213
+ sources .add (src .effect .name )
214
+ self .copies .append (CopyItem (src , dst ))
192
215
# TODO: Turn this into an error (pass an Analyzer instance?)
193
216
assert sources & destinations == set (), (
194
217
pred .instr .name ,
@@ -202,11 +225,27 @@ def __init__(
202
225
else :
203
226
pred = None # Break
204
227
228
+ # Fix up patterns of copies through UNUSED,
229
+ # e.g. cp(a, UNUSED) + cp(UNUSED, b) -> cp(a, b).
230
+ if any (copy .src .effect .name == UNUSED for copy in self .copies ):
231
+ pred = self .pred
232
+ while pred is not None :
233
+ for copy in self .copies :
234
+ if copy .src .effect .name == UNUSED :
235
+ for pred_copy in pred .copies :
236
+ if pred_copy .dst == copy .src :
237
+ copy .src = pred_copy .src
238
+ break
239
+ pred = pred .pred
240
+
205
241
def adjust_deeper (self , eff : StackEffect ) -> None :
206
242
for peek in self .peeks :
207
243
peek .offset .deeper (eff )
208
244
for poke in self .pokes :
209
245
poke .offset .deeper (eff )
246
+ for copy in self .copies :
247
+ copy .src .offset .deeper (eff )
248
+ copy .dst .offset .deeper (eff )
210
249
self .min_offset .deeper (eff )
211
250
self .final_offset .deeper (eff )
212
251
@@ -215,6 +254,9 @@ def adjust_higher(self, eff: StackEffect) -> None:
215
254
peek .offset .higher (eff )
216
255
for poke in self .pokes :
217
256
poke .offset .higher (eff )
257
+ for copy in self .copies :
258
+ copy .src .offset .higher (eff )
259
+ copy .dst .offset .higher (eff )
218
260
self .min_offset .higher (eff )
219
261
self .final_offset .higher (eff )
220
262
@@ -248,8 +290,8 @@ def add(eff: StackEffect) -> None:
248
290
vars [eff .name ] = eff
249
291
250
292
for copy in self .copies :
251
- add (copy .src )
252
- add (copy .dst )
293
+ add (copy .src . effect )
294
+ add (copy .dst . effect )
253
295
for peek in self .peeks :
254
296
add (peek .effect )
255
297
for poke in self .pokes :
@@ -365,8 +407,11 @@ def write_components(
365
407
out .emit (f"// { mgr .instr .name } " )
366
408
367
409
for copy in mgr .copies :
368
- if copy .src .name != copy .dst .name :
369
- out .assign (copy .dst , copy .src )
410
+ copy_src_effect = copy .src .effect
411
+ if copy_src_effect .name != copy .dst .effect .name :
412
+ if copy_src_effect .name == UNUSED :
413
+ copy_src_effect = copy .src .as_stack_effect ()
414
+ out .assign (copy .dst .effect , copy_src_effect )
370
415
for peek in mgr .peeks :
371
416
out .assign (
372
417
peek .effect ,
0 commit comments