Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 603d49dffa99
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: adf18bb04263
Choose a head ref
  • 4 commits
  • 5 files changed
  • 1 contributor

Commits on Jul 19, 2015

  1. 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.
    whitequark committed Jul 19, 2015
    Copy the full SHA
    f212ec0 View commit details
  2. Fix IRGenerator.append(loc=...).

    whitequark committed Jul 19, 2015
    Copy the full SHA
    8eedb3b View commit details
  3. Use ".k" instead of "k" for the finalizer continuation variable.

    The dot signifies that this is an internal variable and it
    does not need to be tracked as if it was a user-defined one.
    whitequark committed Jul 19, 2015
    Copy the full SHA
    4bd83fb View commit details
  4. Fix assignment to tuples in IRGenerator.

    whitequark committed Jul 19, 2015
    Copy the full SHA
    adf18bb View commit details
11 changes: 1 addition & 10 deletions artiq/compiler/analyses/domination.py
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
# 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 @@ def __init__(self, func):
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 @@ def __init__(self, func):

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
7 changes: 6 additions & 1 deletion artiq/compiler/ir.py
Original file line number Diff line number Diff line change
@@ -261,6 +261,11 @@ def remove_from_parent(self):
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 @@ def remove(self, basic_block):
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]

1 change: 1 addition & 0 deletions artiq/compiler/transforms/__init__.py
Original file line number Diff line number Diff line change
@@ -2,3 +2,4 @@
from .inferencer import Inferencer
from .int_monomorphizer import IntMonomorphizer
from .ir_generator import IRGenerator
from .dead_code_eliminator import DeadCodeEliminator
19 changes: 19 additions & 0 deletions artiq/compiler/transforms/dead_code_eliminator.py
Original file line number Diff line number Diff line change
@@ -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()
32 changes: 16 additions & 16 deletions artiq/compiler/transforms/ir_generator.py
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ def append(self, insn, block=None, loc=None):
block = self.current_block

if insn.loc is None:
insn.loc = self.current_loc
insn.loc = loc
return block.append(insn)

def terminate(self, insn):
@@ -424,30 +424,30 @@ def visit_Try(self, node):

if any(node.finalbody):
# k for continuation
final_state = self.append(ir.Alloc([], ir.TEnvironment({ "k": ir.TBasicBlock() })))
final_state = self.append(ir.Alloc([], ir.TEnvironment({ ".k": ir.TBasicBlock() })))
final_targets = []

if self.break_target is not None:
break_proxy = self.add_block("try.break")
old_break, self.break_target = self.break_target, break_proxy
break_proxy.append(ir.SetLocal(final_state, "k", old_break))
break_proxy.append(ir.SetLocal(final_state, ".k", old_break))
final_targets.append(old_break)
if self.continue_target is not None:
continue_proxy = self.add_block("try.continue")
old_continue, self.continue_target = self.continue_target, continue_proxy
continue_proxy.append(ir.SetLocal(final_state, "k", old_continue))
continue_proxy.append(ir.SetLocal(final_state, ".k", old_continue))
final_targets.append(old_continue)

return_proxy = self.add_block("try.return")
old_return, self.return_target = self.return_target, return_proxy
if old_return is not None:
return_proxy.append(ir.SetLocal(final_state, "k", old_return))
return_proxy.append(ir.SetLocal(final_state, ".k", old_return))
final_targets.append(old_return)
else:
return_action = self.add_block("try.doreturn")
value = return_action.append(ir.GetLocal(self.current_private_env, ".return"))
return_action.append(ir.Return(value))
return_proxy.append(ir.SetLocal(final_state, "k", return_action))
return_proxy.append(ir.SetLocal(final_state, ".k", return_action))
final_targets.append(return_action)

body = self.add_block("try.body")
@@ -489,7 +489,7 @@ def visit_Try(self, node):
self.visit(node.finalbody)

if not self.current_block.is_terminated():
dest = self.append(ir.GetLocal(final_state, "k"))
dest = self.append(ir.GetLocal(final_state, ".k"))
self.append(ir.IndirectBranch(dest, final_targets))

tail = self.add_block("try.tail")
@@ -501,11 +501,11 @@ def visit_Try(self, node):
return_proxy.append(ir.Branch(finalizer))
if not body.is_terminated():
if any(node.finalbody):
body.append(ir.SetLocal(final_state, "k", tail))
body.append(ir.SetLocal(final_state, ".k", tail))
body.append(ir.Branch(finalizer))
for handler in handlers:
if not handler.is_terminated():
handler.append(ir.SetLocal(final_state, "k", tail))
handler.append(ir.SetLocal(final_state, ".k", tail))
handler.append(ir.Branch(tail))
else:
body.append(ir.Branch(tail))
@@ -721,22 +721,22 @@ def visit_TupleT(self, node):
else:
try:
old_assign = self.current_assign
for index, elt in enumerate(node.elts):
for index, elt_node in enumerate(node.elts):
self.current_assign = \
self.append(ir.GetAttr(old_assign, index,
name="{}.{}".format(old_assign.name,
_readable_name(index))))
self.visit(elt)
name="{}.{}".format(old_assign.name, index)),
loc=elt_node.loc)
self.visit(elt_node)
finally:
self.current_assign = old_assign

def visit_ListT(self, node):
if self.current_assign is None:
elts = [self.visit(elt) for elt in node.elts]
elts = [self.visit(elt_node) for elt_node in node.elts]
lst = self.append(ir.Alloc([ir.Constant(len(node.elts), self._size_type)],
node.type))
for index, elt in enumerate(elts):
self.append(ir.SetElem(lst, ir.Constant(index, self._size_type), elt))
for index, elt_node in enumerate(elts):
self.append(ir.SetElem(lst, ir.Constant(index, self._size_type), elt_node))
return lst
else:
length = self.append(ir.Builtin("len", [self.current_assign], self._size_type))