@@ -149,10 +149,12 @@ def __init__(self, downstream=None):
149149 self .downstream = downstream
150150
151151 def emit (self , insn ):
152+ #print(self.__class__.__name__, "emits", insn)
152153 if self .downstream :
153154 self .downstream .handle_insn (insn )
154155
155156 def handle_insn (self , insn ):
157+ #print(self.__class__.__name__, "receives", insn)
156158 self .insn_func_map [type (insn )](insn )
157159
158160 def handle_fn_begin (self , insn ):
@@ -257,82 +259,170 @@ def node_debug(node):
257259
258260class OptimizerLoop (IRVisitor ):
259261
260- def handle_insn (self , insn ):
261- #print("DOWNSTREAM", node_debug(insn))
262- super ().handle_insn (insn )
262+ def __init__ (self , upstream , downstream ):
263+ super ().__init__ (downstream )
264+ self .upstream = upstream
265+ self .buffer = []
266+
267+ def emit (self , insn ):
268+ self .buffer .append (insn )
269+
270+ def handle_fn_end (self , insn ):
271+ self .emit (insn )
272+ if self ._success :
273+ for insn in self .buffer :
274+ self .upstream .handle_insn (insn )
275+ else :
276+ for insn in self .buffer :
277+ super ().emit (insn )
278+ self .buffer = []
279+
280+ def new_fn (self ):
281+ self .buffer = []
282+ self ._success = False
283+
284+ def report_success (self ):
285+ self ._success = True
263286
264287class Optimizer (IRVisitor ):
265288
266289 def __init__ (self , downstream ):
267- optimizer = OptimizerLoop (downstream )
268- optimizer = ConstantElimination (optimizer )
269- optimizer = JumpElimination (optimizer )
290+ loop = OptimizerLoop (self , downstream )
291+ optimizer = loop
292+ optimizer = ConstantElimination (loop , optimizer )
293+ optimizer = JumpElimination (loop , optimizer )
294+ optimizer = DeadCodeElimination (loop , optimizer )
270295 super ().__init__ (optimizer )
296+ self .loop = loop
297+
298+ def handle_entity_local (self , insn ):
299+ # This appears before functions begin, pass straight through
300+ self .loop .downstream .handle_insn (insn )
301+
302+ def handle_fn_begin (self , insn ):
303+ self .loop .new_fn ()
304+ self .emit (insn )
271305
272306 def handle_insn (self , insn ):
273307 #print("UPSTREAM", node_debug(insn))
274308 super ().handle_insn (insn )
275309
276- class JumpElimination (IRVisitor ):
310+ class OptimizerVisitor (IRVisitor ):
277311
278- def __init__ (self , downstream ):
312+ def __init__ (self , loop , downstream ):
279313 super ().__init__ (downstream )
280- self .buffer = []
281- self .aliases = {}
282- self .previous = None
314+ self .loop = loop
315+ self .init ()
316+
317+ def init (self ):
318+ pass
319+
320+ def success (self ):
321+ # print("SUCCESS from", self.__class__.__name__)
322+ self .loop .report_success ()
323+
324+ class DeadCodeElimination (OptimizerVisitor ):
325+
326+ def init (self ):
327+ self .dead = False
283328
284329 def emit (self , insn ):
285- self .buffer .append (insn )
286- self .previous = insn
330+ if not self .dead :
331+ super ().emit (insn )
332+
333+ def handle_entity_local (self , insn ):
334+ self .dead = False
335+ self .emit (insn )
287336
288337 def handle_fn_begin (self , insn ):
338+ self .dead = False
289339 self .emit (insn )
290340
291341 def handle_fn_end (self , insn ):
342+ self .dead = False
292343 self .emit (insn )
293- for i in self .buffer :
294- if isinstance (i , (IR .Jump , IR .JumpIf , IR .JumpIfNot )):
295- aliases = self .aliases [i .dest ]
296- if aliases :
297- i = i ._replace (dest = aliases [0 ])
298- super ().emit (i )
344+
345+ def handle_jump (self , insn ):
346+ self .emit (insn )
347+ self .dead = True
348+
349+ def handle_label (self , insn ):
350+ self .dead = False
351+ self .emit (insn )
352+
353+ class JumpElimination (OptimizerVisitor ):
354+
355+ def init (self ):
299356 self .buffer = []
300357 self .aliases = {}
301358 self .previous = None
359+ self .label_used = {}
360+ self .aliases_of = {}
302361
303- def handle_label (self , label ):
304- if not label in self .aliases :
305- self .aliases [label ] = []
306- if isinstance (self .previous , IR .Label ):
307- self .aliases [label ].append (self .previous )
308- emit = False
309- else :
310- emit = True
311- for i in range (1 , 3 ):
312- if len (self .buffer ) < i :
313- continue
314- prev = self .buffer [- i ]
315- if isinstance (prev , (IR .Jump , IR .JumpIf , IR .JumpIfNot )):
316- if prev .dest == label or \
317- prev .dest in self .aliases [label ]:
318- self .buffer .pop (- i )
319- break
320- if emit :
321- self .emit (label )
362+ def emit (self , insn ):
363+ self .buffer .append (insn )
364+ self .previous = insn
365+
366+ def is_jump (self , insn ):
367+ return isinstance (insn , (IR .Jump , IR .JumpIf , IR .JumpIfNot ))
322368
323369 def handle_jump (self , insn ):
370+ self .uses_label (insn .dest )
324371 self .emit (insn )
325372
326373 def handle_jump_if (self , insn ):
374+ self .uses_label (insn .dest )
327375 self .emit (insn )
328376
329377 def handle_jump_if_not (self , insn ):
378+ self .uses_label (insn .dest )
330379 self .emit (insn )
331380
332- class ConstantElimination (IRVisitor ):
381+ def uses_label (self , label ):
382+ self .label_used [label ] = True
333383
334- def __init__ (self , downstream ):
335- super ().__init__ (downstream )
384+ def handle_fn_begin (self , insn ):
385+ self .init ()
386+ self .emit (insn )
387+
388+ def label_is_used (self , label ):
389+ if label in self .label_used :
390+ return True
391+ if label not in self .aliases_of :
392+ return False
393+ # Label is used if any of its aliases are used
394+ return any (filter (self .label_is_used , self .aliases_of [label ]))
395+
396+ def handle_fn_end (self , insn ):
397+ self .emit (insn )
398+ for insn in self .buffer :
399+ if self .is_jump (insn ):
400+ old_label = insn .dest
401+ if old_label in self .aliases :
402+ self .success ()
403+ insn = insn ._replace (dest = self .aliases [old_label ])
404+ elif isinstance (insn , IR .Label ):
405+ if not self .label_is_used (insn ):
406+ # Label not used, remove
407+ self .success ()
408+ continue
409+ super ().emit (insn )
410+
411+ def handle_label (self , label ):
412+ if isinstance (self .previous , IR .Label ):
413+ # If the previous was a label, then we are simply an alias of it
414+ self .aliases [label ] = self .previous
415+ self .aliases_of .setdefault (self .previous , []).append (label )
416+ return
417+ if isinstance (self .previous , IR .Jump ):
418+ # If the previous was a jump to this label, eliminate the jump
419+ if self .previous .dest == label :
420+ self .buffer .pop ()
421+ self .emit (label )
422+
423+ class ConstantElimination (OptimizerVisitor ):
424+
425+ def init (self ):
336426 self .slot_value_map = {}
337427
338428 def literal (self , ref ):
@@ -359,11 +449,27 @@ def handle_jump(self, insn):
359449
360450 def handle_jump_if (self , insn ):
361451 self .slot_value_map = {}
362- self .emit (insn )
452+ cond = self .literal (insn .cond )
453+ if cond is not None :
454+ self .success ()
455+ if cond != 0 :
456+ self .emit (IR .Jump (insn .dest ))
457+ else :
458+ pass # just don't jump
459+ else :
460+ self .emit (insn )
363461
364462 def handle_jump_if_not (self , insn ):
365463 self .slot_value_map = {}
366- self .emit (insn )
464+ cond = self .literal (insn .cond )
465+ if cond is not None :
466+ self .success ()
467+ if cond != 0 :
468+ pass # just don't jump
469+ else :
470+ self .emit (IR .Jump (insn .dest ))
471+ else :
472+ self .emit (insn )
367473
368474 def handle_call (self , insn ):
369475 self .slot_value_map = {}
@@ -401,10 +507,13 @@ def handle_operation(self, insn):
401507 val = func (left , right )
402508 if type (val ) == bool : # for boolean evaluations
403509 val = 1 if val else 0
510+ self .success ()
404511 self .handle_insn (IR .Move (self .int (val ), insn .dest ))
405512 elif i_mode & 2 and left == ident :
513+ self .success ()
406514 self .handle_insn (IR .Move (insn .right , insn .dest ))
407515 elif i_mode & 1 and right == ident :
516+ self .success ()
408517 self .handle_insn (IR .Move (insn .left , insn .dest ))
409518 else :
410519 if insn .dest in self .slot_value_map :
0 commit comments