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: e263b6352713
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: 20ca97485c7b
Choose a head ref
  • 3 commits
  • 2 files changed
  • 1 contributor

Commits on Sep 26, 2014

  1. Copy the full SHA
    f332def View commit details
  2. Copy the full SHA
    8852dd3 View commit details
  3. Copy the full SHA
    20ca974 View commit details
Showing with 37 additions and 17 deletions.
  1. +20 −4 artiq/py2llvm/ast_body.py
  2. +17 −13 artiq/transforms/unroll_loops.py
24 changes: 20 additions & 4 deletions artiq/py2llvm/ast_body.py
Original file line number Diff line number Diff line change
@@ -44,6 +44,7 @@ def __init__(self, env, ns, builder=None):
self.builder = builder
self._break_stack = []
self._eid_stack = []
self._exception_level_stack = [0]

# builder can be None for visit_expression
def visit_expression(self, node):
@@ -206,19 +207,27 @@ def _visit_stmt_If(self, node):

self.builder.position_at_end(merge_block)

def _enter_loop_body(self, break_block):
self._break_stack.append(break_block)
self._exception_level_stack.append(0)

def _leave_loop_body(self):
self._exception_level_stack.pop()

def _visit_stmt_While(self, node):
function = self.builder.basic_block.function
body_block = function.append_basic_block("w_body")
else_block = function.append_basic_block("w_else")
merge_block = function.append_basic_block("w_merge")
self._break_stack.append(merge_block)

condition = self.visit_expression(node.test).o_bool(self.builder)
self.builder.cbranch(
condition.auto_load(self.builder), body_block, else_block)

self.builder.position_at_end(body_block)
self._enter_loop_body(merge_block)
self.visit_statements(node.body)
self._leave_loop_body()
if not is_terminated(self.builder.basic_block):
condition = self.visit_expression(node.test).o_bool(self.builder)
self.builder.cbranch(
@@ -230,14 +239,12 @@ def _visit_stmt_While(self, node):
self.builder.branch(merge_block)

self.builder.position_at_end(merge_block)
self._break_stack.pop()

def _visit_stmt_For(self, node):
function = self.builder.basic_block.function
body_block = function.append_basic_block("f_body")
else_block = function.append_basic_block("f_else")
merge_block = function.append_basic_block("f_merge")
self._break_stack.append(merge_block)

it = self.visit_expression(node.iter)
target = self.visit_expression(node.target)
@@ -249,7 +256,9 @@ def _visit_stmt_For(self, node):

self.builder.position_at_end(body_block)
target.set_value(self.builder, itval)
self._enter_loop_body(merge_block)
self.visit_statements(node.body)
self._leave_loop_body()
if not is_terminated(self.builder.basic_block):
cont = it.o_next(self.builder)
self.builder.cbranch(
@@ -261,16 +270,21 @@ def _visit_stmt_For(self, node):
self.builder.branch(merge_block)

self.builder.position_at_end(merge_block)
self._break_stack.pop()

def _visit_stmt_Break(self, node):
exception_levels = self._exception_level_stack[-1]
if exception_levels:
self.env.build_pop(self.builder, exception_levels)
self.builder.branch(self._break_stack[-1])

def _visit_stmt_Return(self, node):
if node.value is None:
val = base_types.VNone()
else:
val = self.visit_expression(node.value)
exception_levels = sum(self._exception_level_stack)
if exception_levels:
self.env.build_pop(self.builder, exception_levels)
if isinstance(val, base_types.VNone):
self.builder.ret_void()
else:
@@ -336,7 +350,9 @@ def _visit_stmt_Try(self, node):
self.builder.cbranch(exception_occured, exc_block, noexc_block)

self.builder.position_at_end(noexc_block)
self._exception_level_stack[-1] += 1
self.visit_statements(node.body)
self._exception_level_stack[-1] -= 1
if not is_terminated(self.builder.basic_block):
self.env.build_pop(self.builder, 1)
self.visit_statements(node.orelse)
30 changes: 17 additions & 13 deletions artiq/transforms/unroll_loops.py
Original file line number Diff line number Diff line change
@@ -15,21 +15,25 @@ def _count_stmts(node):


def _loop_breakable(node):
if isinstance(node, ast.Break):
return 1
elif isinstance(node, ast.Return):
return 2
elif isinstance(node, list):
return max(map(_loop_breakable, node), default=0)
if isinstance(node, list):
return any(map(_loop_breakable, node))
elif isinstance(node, (ast.Break, ast.Continue)):
return True
elif isinstance(node, ast.With):
return _loop_breakable(node.body)
elif isinstance(node, ast.If):
return max(_loop_breakable(node.body), _loop_breakable(node.orelse))
elif isinstance(node, (ast.For, ast.While)):
bb = _loop_breakable(node.body)
if bb == 1:
bb = 0
return max(bb, _loop_breakable(node.orelse))
return _loop_breakable(node.body) or _loop_breakable(node.orelse)
elif isinstance(node, ast.Try):
if (_loop_breakable(node.body)
or _loop_breakable(node.orelse)
or _loop_breakable(node.finalbody)):
return True
for handler in node.handlers:
if _loop_breakable(handler.body):
return True
return False
else:
return 0
return False


class _LoopUnroller(ast.NodeTransformer):