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: d0f86e05d083
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: cb9e7d15bf2a
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Nov 20, 2015

  1. Reformat.

    whitequark committed Nov 20, 2015
    Copy the full SHA
    cc623c1 View commit details
  2. Copy the full SHA
    cb9e7d1 View commit details
Showing with 64 additions and 57 deletions.
  1. +11 −6 artiq/compiler/iodelay.py
  2. +53 −51 artiq/compiler/transforms/interleaver.py
17 changes: 11 additions & 6 deletions artiq/compiler/iodelay.py
Original file line number Diff line number Diff line change
@@ -158,18 +158,23 @@ class Add(BinOpFixpoint):
_op = lambda a, b: a + b
_fixpoint = 0

class Sub(BinOpFixpoint):
_priority = 2
_symbol = "-"
_op = lambda a, b: a - b
_fixpoint = 0

class Mul(BinOpFixpoint):
_priority = 1
_symbol = "*"
_op = lambda a, b: a * b
_fixpoint = 1

class Sub(BinOp):
_priority = 2
_symbol = "-"
_op = lambda a, b: a - b

def _fold_binop(self, lhs, rhs):
if isinstance(rhs, Const) and rhs.value == 0:
return lhs
else:
return super()._fold_binop(lhs, rhs)

class Div(BinOp):
def _fold_binop(self, lhs, rhs):
if isinstance(rhs, Const) and rhs.value == 1:
104 changes: 53 additions & 51 deletions artiq/compiler/transforms/interleaver.py
Original file line number Diff line number Diff line change
@@ -45,55 +45,57 @@ def process_function(self, func):

postdom_tree = None
for insn in func.instructions():
if isinstance(insn, ir.Parallel):
# Lazily compute dominators.
if postdom_tree is None:
postdom_tree = domination.PostDominatorTree(func)

interleave_until = postdom_tree.immediate_dominator(insn.basic_block)
assert (interleave_until is not None) # no nonlocal flow in `with parallel`

target_block = insn.basic_block
target_time = 0
source_blocks = insn.basic_block.successors()
source_times = [0 for _ in source_blocks]

while len(source_blocks) > 0:
def iodelay_of_block(block):
terminator = block.terminator()
if isinstance(terminator, ir.Delay):
# We should be able to fold everything without free variables.
assert iodelay.is_const(terminator.expr)
return terminator.expr.value
else:
return 0

def time_after_block(pair):
index, block = pair
return source_times[index] + iodelay_of_block(block)

index, source_block = min(enumerate(source_blocks), key=time_after_block)
source_block_delay = iodelay_of_block(source_block)

target_terminator = target_block.terminator()
if isinstance(target_terminator, (ir.Delay, ir.Branch)):
target_terminator.set_target(source_block)
elif isinstance(target_terminator, ir.Parallel):
target_terminator.replace_with(ir.Branch(source_block))
if not isinstance(insn, ir.Parallel):
continue

# Lazily compute dominators.
if postdom_tree is None:
postdom_tree = domination.PostDominatorTree(func)

interleave_until = postdom_tree.immediate_dominator(insn.basic_block)
assert (interleave_until is not None) # no nonlocal flow in `with parallel`

target_block = insn.basic_block
target_time = 0
source_blocks = insn.basic_block.successors()
source_times = [0 for _ in source_blocks]

while len(source_blocks) > 0:
def iodelay_of_block(block):
terminator = block.terminator()
if isinstance(terminator, ir.Delay):
# We should be able to fold everything without free variables.
assert iodelay.is_const(terminator.expr)
return terminator.expr.value
else:
assert False

new_source_block = postdom_tree.immediate_dominator(source_block)
assert (new_source_block is not None)
assert delay_free_subgraph(source_block, new_source_block)

target_block = source_block
target_time += source_block_delay

if new_source_block == interleave_until:
# We're finished with this branch.
del source_blocks[index]
del source_times[index]
else:
source_blocks[index] = new_source_block
source_times[index] = target_time
return 0

def time_after_block(pair):
index, block = pair
return source_times[index] + iodelay_of_block(block)

index, source_block = min(enumerate(source_blocks), key=time_after_block)
source_block_delay = iodelay_of_block(source_block)

target_terminator = target_block.terminator()
if isinstance(target_terminator, (ir.Delay, ir.Branch)):
target_terminator.set_target(source_block)
elif isinstance(target_terminator, ir.Parallel):
target_terminator.replace_with(ir.Branch(source_block))
else:
assert False

target_block = source_block
target_time += source_block_delay

new_source_block = postdom_tree.immediate_dominator(source_block)
assert (new_source_block is not None)
assert delay_free_subgraph(source_block, new_source_block)

if new_source_block == interleave_until:
# We're finished with this branch.
del source_blocks[index]
del source_times[index]
else:
source_blocks[index] = new_source_block
source_times[index] = target_time