Skip to content

Commit 1e8c983

Browse files
committedOct 29, 2014
transforms: add dead code removal
1 parent be94a8b commit 1e8c983

File tree

4 files changed

+84
-20
lines changed

4 files changed

+84
-20
lines changed
 

‎artiq/coredevice/core.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from artiq.transforms.lower_units import lower_units
55
from artiq.transforms.remove_inter_assigns import remove_inter_assigns
66
from artiq.transforms.fold_constants import fold_constants
7+
from artiq.transforms.remove_dead_code import remove_dead_code
78
from artiq.transforms.unroll_loops import unroll_loops
89
from artiq.transforms.interleave import interleave
910
from artiq.transforms.lower_time import lower_time
@@ -43,7 +44,7 @@ def __init__(self, core_com, runtime_env=None):
4344

4445
def run(self, k_function, k_args, k_kwargs):
4546
# transform/simplify AST
46-
_debug_unparse = _make_debug_unparse("fold_constants_2")
47+
_debug_unparse = _make_debug_unparse("remove_dead_code")
4748

4849
func_def, rpc_map, exception_map = inline(
4950
self, k_function, k_args, k_kwargs)
@@ -75,6 +76,9 @@ def run(self, k_function, k_args, k_kwargs):
7576
fold_constants(func_def)
7677
_debug_unparse("fold_constants_2", func_def)
7778

79+
remove_dead_code(func_def)
80+
_debug_unparse("remove_dead_code", func_def)
81+
7882
# compile to machine code and run
7983
binary = get_runtime_binary(self.runtime_env, func_def)
8084
self.core_com.load(binary)

‎artiq/transforms/remove_dead_code.py

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import ast
2+
3+
from artiq.transforms.tools import is_replaceable
4+
5+
6+
class _SourceLister(ast.NodeVisitor):
7+
def __init__(self):
8+
self.sources = set()
9+
10+
def visit_Name(self, node):
11+
if isinstance(node.ctx, ast.Load):
12+
self.sources.add(node.id)
13+
14+
15+
class _DeadCodeRemover(ast.NodeTransformer):
16+
def __init__(self, kept_targets):
17+
self.kept_targets = kept_targets
18+
19+
def visit_Assign(self, node):
20+
new_targets = []
21+
for target in node.targets:
22+
if not (isinstance(target, ast.Name)
23+
and target.id not in self.kept_targets):
24+
new_targets.append(target)
25+
if not new_targets and is_replaceable(node.value):
26+
return None
27+
else:
28+
return node
29+
30+
def visit_AugAssign(self, node):
31+
if (isinstance(node.target, ast.Name)
32+
and node.target.id not in self.kept_targets
33+
and is_replaceable(node.value)):
34+
return None
35+
else:
36+
return node
37+
38+
def visit_If(self, node):
39+
if isinstance(node.test, ast.NameConstant):
40+
if node.test.value:
41+
return node.body
42+
else:
43+
return node.orelse
44+
else:
45+
return node
46+
47+
def visit_While(self, node):
48+
if isinstance(node.test, ast.NameConstant) and not node.test.value:
49+
return node.orelse
50+
else:
51+
return node
52+
53+
54+
def remove_dead_code(func_def):
55+
sl = _SourceLister()
56+
sl.visit(func_def)
57+
_DeadCodeRemover(sl.sources).visit(func_def)

‎artiq/transforms/remove_inter_assigns.py

+2-19
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,7 @@
11
import ast
22
from copy import copy, deepcopy
33

4-
5-
_replaceable_funcs = {
6-
"bool", "int", "float", "round",
7-
"int64", "round64", "Fraction",
8-
}
9-
10-
11-
def _is_replaceable(value):
12-
if isinstance(value, (ast.NameConstant, ast.Num, ast.Str)):
13-
return True
14-
elif isinstance(value, ast.BinOp):
15-
return _is_replaceable(value.left) and _is_replaceable(value.right)
16-
elif isinstance(value, ast.BoolOp):
17-
return all(_is_replaceable(v) for v in value.values)
18-
elif isinstance(value, ast.Call) and isinstance(value.func, ast.Name):
19-
return value.func.id in _replaceable_funcs
20-
else:
21-
return False
4+
from artiq.transforms.tools import is_replaceable
225

236

247
class _TargetLister(ast.NodeVisitor):
@@ -47,7 +30,7 @@ def visit_Name(self, node):
4730

4831
def visit_Assign(self, node):
4932
self.generic_visit(node)
50-
if _is_replaceable(node.value):
33+
if is_replaceable(node.value):
5134
for target in node.targets:
5235
if isinstance(target, ast.Name):
5336
self.replacements[target.id] = node.value

‎artiq/transforms/tools.py

+20
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,23 @@ def eval_constant(node):
7575
raise NotConstant
7676
else:
7777
raise NotConstant
78+
79+
80+
_replaceable_funcs = {
81+
"bool", "int", "float", "round",
82+
"int64", "round64", "Fraction",
83+
"Quantity"
84+
}
85+
86+
87+
def is_replaceable(expr):
88+
if isinstance(expr, (ast.NameConstant, ast.Num, ast.Str)):
89+
return True
90+
elif isinstance(expr, ast.BinOp):
91+
return is_replaceable(expr.left) and is_replaceable(expr.right)
92+
elif isinstance(expr, ast.BoolOp):
93+
return all(is_replaceable(v) for v in expr.values)
94+
elif isinstance(expr, ast.Call) and isinstance(expr.func, ast.Name):
95+
return expr.func.id in _replaceable_funcs
96+
else:
97+
return False

0 commit comments

Comments
 (0)
Please sign in to comment.