From f212ec0263b2b7f7822ae56c2f9f7d111f0bc196 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 19 Jul 2015 10:29:14 +0300 Subject: [PATCH] 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. --- artiq/compiler/analyses/domination.py | 11 +---------- artiq/compiler/ir.py | 7 ++++++- artiq/compiler/transforms/__init__.py | 1 + .../transforms/dead_code_eliminator.py | 19 +++++++++++++++++++ 4 files changed, 27 insertions(+), 11 deletions(-) create mode 100644 artiq/compiler/transforms/dead_code_eliminator.py diff --git a/artiq/compiler/analyses/domination.py b/artiq/compiler/analyses/domination.py index 8963cf189..7fbd4d231 100644 --- a/artiq/compiler/analyses/domination.py +++ b/artiq/compiler/analyses/domination.py @@ -13,7 +13,7 @@ from functools import reduce, cmp_to_key # also dominates node n class DominatorTree: def __init__(self, func): - entry = func.get_entry() + entry = func.entry() self.dominated_by = { entry: {entry} } for block in func.basic_blocks: @@ -28,10 +28,6 @@ class DominatorTree: if block == entry: continue - if not any(predecessors[block]): - # Unreachable blocks are dominated by everything - continue - new_dominated_by = {block}.union( reduce(lambda a, b: a.intersection(b), (self.dominated_by[pred] for pred in predecessors[block]))) @@ -41,8 +37,3 @@ class DominatorTree: if not changed: 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 diff --git a/artiq/compiler/ir.py b/artiq/compiler/ir.py index ad36fbbeb..1aaf0d97f 100644 --- a/artiq/compiler/ir.py +++ b/artiq/compiler/ir.py @@ -261,6 +261,11 @@ class BasicBlock(NamedValue): if self.function is not None: self.function.remove(self) + def erase(self): + for insn in self.instructions: + insn.erase() + self.remove_from_parent() + def prepend(self, insn): assert isinstance(insn, Instruction) insn.set_basic_block(self) @@ -386,7 +391,7 @@ class Function: basic_block._detach() self.basic_blocks.remove(basic_block) - def get_entry(self): + def entry(self): assert any(self.basic_blocks) return self.basic_blocks[0] diff --git a/artiq/compiler/transforms/__init__.py b/artiq/compiler/transforms/__init__.py index 4f059a686..64dca0906 100644 --- a/artiq/compiler/transforms/__init__.py +++ b/artiq/compiler/transforms/__init__.py @@ -2,3 +2,4 @@ from .asttyped_rewriter import ASTTypedRewriter from .inferencer import Inferencer from .int_monomorphizer import IntMonomorphizer from .ir_generator import IRGenerator +from .dead_code_eliminator import DeadCodeEliminator diff --git a/artiq/compiler/transforms/dead_code_eliminator.py b/artiq/compiler/transforms/dead_code_eliminator.py new file mode 100644 index 000000000..92d82b4a7 --- /dev/null +++ b/artiq/compiler/transforms/dead_code_eliminator.py @@ -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()