forked from M-Labs/artiq
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:
parent
603d49dffa
commit
f212ec0263
|
@ -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
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
Loading…
Reference in New Issue