Add a trivial dead code elimination transform.

Its purpose is to sweep up basic blocks with no predecessors,
which are annoying to handle explicitly elsewhere.
This commit is contained in:
whitequark 2015-07-19 10:29:14 +03:00
parent 603d49dffa
commit f212ec0263
4 changed files with 27 additions and 11 deletions

View File

@ -13,7 +13,7 @@ from functools import reduce, cmp_to_key
# also dominates node n # also dominates node n
class DominatorTree: class DominatorTree:
def __init__(self, func): def __init__(self, func):
entry = func.get_entry() entry = func.entry()
self.dominated_by = { entry: {entry} } self.dominated_by = { entry: {entry} }
for block in func.basic_blocks: for block in func.basic_blocks:
@ -28,10 +28,6 @@ class DominatorTree:
if block == entry: if block == entry:
continue continue
if not any(predecessors[block]):
# Unreachable blocks are dominated by everything
continue
new_dominated_by = {block}.union( new_dominated_by = {block}.union(
reduce(lambda a, b: a.intersection(b), reduce(lambda a, b: a.intersection(b),
(self.dominated_by[pred] for pred in predecessors[block]))) (self.dominated_by[pred] for pred in predecessors[block])))
@ -41,8 +37,3 @@ class DominatorTree:
if not changed: if not changed:
break break
def in_domination_order(self):
blocks = list(self.dominated_by.keys())
blocks.sort(key=cmp_to_key(lambda a, b: a in self.dominated_by[b]))
return blocks

View File

@ -261,6 +261,11 @@ class BasicBlock(NamedValue):
if self.function is not None: if self.function is not None:
self.function.remove(self) self.function.remove(self)
def erase(self):
for insn in self.instructions:
insn.erase()
self.remove_from_parent()
def prepend(self, insn): def prepend(self, insn):
assert isinstance(insn, Instruction) assert isinstance(insn, Instruction)
insn.set_basic_block(self) insn.set_basic_block(self)
@ -386,7 +391,7 @@ class Function:
basic_block._detach() basic_block._detach()
self.basic_blocks.remove(basic_block) self.basic_blocks.remove(basic_block)
def get_entry(self): def entry(self):
assert any(self.basic_blocks) assert any(self.basic_blocks)
return self.basic_blocks[0] return self.basic_blocks[0]

View File

@ -2,3 +2,4 @@ from .asttyped_rewriter import ASTTypedRewriter
from .inferencer import Inferencer from .inferencer import Inferencer
from .int_monomorphizer import IntMonomorphizer from .int_monomorphizer import IntMonomorphizer
from .ir_generator import IRGenerator from .ir_generator import IRGenerator
from .dead_code_eliminator import DeadCodeEliminator

View File

@ -0,0 +1,19 @@
"""
:class:`DeadCodeEliminator` is a very simple dead code elimination
transform: it only removes basic blocks with no predecessors.
"""
from .. import ir
class DeadCodeEliminator:
def __init__(self, engine):
self.engine = engine
def process(self, functions):
for func in functions:
self.process_function(func)
def process_function(self, func):
for block in func.basic_blocks:
if not any(block.predecessors()) and block != func.entry():
block.erase()